preamble
I don't realize it's already September, it's the start of the school year, and the project wall I've been wanting to do every year isn't even a shadow of its former self...😂
There's been so much going on in my life lately that it's resulted in a complete lack of motivation to want to write a post, but no matter how much I procrastinate I still have to keep track of it, so feel free to write~
This time is a small project in July, not to talk about any technical content, it is a friendly development. Backend DjangoStarter v3, front-end use Taro to do WeChat small program.
The fact that the back-end basically nothing to say, basically what pit can be recorded in the small program this piece, I have to say that WeChat is really the history of history, not only the code written with the same defense, the document is a pile 😂
Before reading the Internet there is a saying, just because WeChat do with the defense, only to give the small program developers a moat, now I think of it is quite reasonable, hahaha 😃
back-end
Let's start with the back-end part
Since DjangoStarter, the back-end development of such small projects has gone straight to seconds!
There are a couple of new ones used in this project that I've written about before, so let's just put the link directly~
- Tencent COS Object Storage Integration in Django
- Editing categories with django-treebeard
Managing files with django-filer
Forgot that this has not written an article, then a brief introduction to it, this component can achieve the centralized management of documents (including pictures), but also provides an admin interface, but the UI style is relatively primitive, and the Chinese locale there are bugs, you have to manually modify the normal switch to Chinese. But for this project is enough!
Project address./django-cms/django-filer
Installation.pdm add django-filer
particle marking the following noun as a direct objectfiler
add toINSTALLED_APPS
Li (surname)
increasesrc/config/settings/components/
configure
THUMBNAIL_PROCESSORS = (
'easy_thumbnails.',
'easy_thumbnails.',
'easy_thumbnails.processors.scale_and_crop',
# Subject location aware cropping
# 'filer.thumbnail_processors.scale_and_crop_with_subject_location',
'easy_thumbnails.',
)
FILER_ENABLE_LOGGING = True
Finally, modify the fields that need to be used for attachments
from import FilerImageField
class Brand(ModelExt):
name = ('name (of a thing)', max_length=100)
# logo = (upload_to='brand_logos/')
logo = FilerImageField(
verbose_name='Logo', null=True, blank=True,
related_name='+', on_delete=models.SET_NULL,
)
That's about it. See the official documentation for details.
Writing APIs with ninja
DjangoStarter v3 starts switching from drf to ninja
This ninja is very similar to FastAPI, and is much more comfortable to write than drf, although it can't automatically generate crud interfaces like drf, but it's not much more code to write, and it's more flexible.
(PS: DjangoStarter v3 still supports auto-generation of crud interfaces, and it's also possible to use third-party libraries to auto-generate ninja-based crud interfaces, but I haven't used them yet, so see the extensions section below)
For example, with the django-filer library mentioned above, the image field actually points to the model's foreign key, so if the interface doesn't do anything with it, the data generated will just be a foreign key ID, so change the schema
class CaseOut(ModelSchema):
cover_image: str
@staticmethod
def resolve_cover_image(obj: Case):
if not obj.cover_image:
return f'https://starblog/Api/PicLib/Random/{}/250/150'
return obj.cover_image.url
class Meta:
model = Case
fields = [
'id', 'is_deleted', 'created_time', 'updated_time', 'name', 'description',
'category', 'car_model', 'part', 'build_time',
]
The above code will put thecover_image
field is rendered as an image address if thecover_image
Returns a random image address if it does not exist.
The schema realizes the separation of logic and data rendering, and the code structure is clearer.
It is also possible to implement more complex logic by simply implementing theresolve_field_name
Just do it the right way.
ninja eco-extension
I just recently found out that django-ninja also has a Chinese web site, which writes a few ninja eco-extensions that feel pretty good, so you can try them out sometime in the future.
Website./
- Ninja JWT - A JSON web token authentication plugin for the Django Ninja REST framework.
- Django Ninja Extra - Django Ninja Extra provides a class-based approach and additional functionality that will accelerate your RESTful API development using Django Ninja.
- Django Ninja CRUD - Django Ninja CRUD is a powerful, declarative, yet somewhat stubborn framework that simplifies the process of developing CRUD (Create, Read, Update, Delete) endpoints using Django Ninja and also provides a declarative, scenario-based approach for testing these endpoints using Django REST Testing (the little brother of this package) to test these endpoints.
Small program component
This time still use Taro to develop mobile, last time is to do H5 (public), this time to try Taro made out of small program how, the actual effect is not bad.
I still choose mobx for status management, I'm used to it, too many wheels on the front-end, too lazy to try the others~.
Compared to the back-end part, there's a little bit more that can be written in an applet (but not much, it's all very simple)
Using tailwindcss in Taro
I recently started using tailwindcss and immediately fell in love with this efficient styling tool (although there will be a long string of classes) but the flaws are, using tailwindcss can be very easy to copy all kinds of styles on the web, and I can also get LLM to write all kinds of styles for me, the productivity pulls full~!
Taro officially provides tailwindcss support, which is great, just follow the official documentation.
See official documentation at./docs/tailwindcss
Share the applet
If it's not actively called, then only registeredonShareAppMessage
event in order to show the forward button when tapping the three dots in the upper right corner; similarly, registering theonShareTimeline
The event can only be shared to the circle of friends.
Accordingly, Taro provides hooks for these two events, just look at the code.
import Taro, {useShareAppMessage, useShareTimeline} from '@tarojs/taro'
const CasePage = () => {
const getCase = async () => {
if (!id) return
const data = await (Number(id))
('get case', data)
setCaseData()
return {
title: `case (law):${}`,
path: (),
imageUrl: .cover_image
}
}
useShareAppMessage(res => {
('Perform a share operation', res)
return {
title: 'case (law)分享',
path: ,
promise: new Promise(resolve => getCase().then((data) => {
// @ts-ignore
resolve(data)
})),
}
})
useShareTimeline(() => {
('Perform the Share with Friends operation')
return {
title: `case (law):${}`,
query: `id=${}`,
imageUrl: caseData.cover_image
}
})
}
With the small program documentation said the same, need to return the same parameters and so on, so look at the documentation directly to the
Proactive sharing
For active sharing, just set the button toshare
The type will do. Taro did the same with the packaging.
<Button type='info' icon={<Share/>} openType='share'>share</Button>
bibliography
- /post/7261774602481369147
- /miniprogram/dev/framework/open-ability/
- /miniprogram/dev/reference/api/#onShareAppMessage-Object-object
user login
In this project I am making a separate page to handle the login, which could also be in the form of a Modal, but at first I was under the illusion of getting the user's information because the documentation describes that getting the user's avatar, nickname, etc. needs to be actively triggered in order to do so, so it's put on a separate page that provides a login button for the user to click on.
But then I found out that the new version of the applet no longer allows you to get information this way ......
The login piece, which Taro also encapsulates, is really just a way of putting the Change the wx to Taro.
const LoginPage = observer(() => {
const handleLogin = async (data: LoginToken) => {
({
token: ,
exp: String(),
})
const userInfo = await ()
('Get user information', userInfo)
=
()
}
const autoLogin = async () => {
({title: 'Logging in', icon: 'loading'})
({
success: async (res) => {
if () {
('Applet Login,gaincode', )
const resp = await ()
('Applet Login,requesting a backend', resp)
await handleLogin()
} else {
('Login Failure!', )
}
}
})
}
}
Get the code after the applet OAuth, call the backend interface to log in, done.
And this part of DjangoStarter v3 is also integrated 🕶
Click on the image to open a larger version
In the image component'sonTap
Called in an event Just remember to pass in the address of the larger image (if the smaller image is a separate address)
<Image
key={} src={}
onTap={() => {
({
current: ,
urls: (i => )
})
}}
className="w-full rounded shadow"
mode="aspectFill"
/>
deployments
This deployment is also a new version of the ship
This project is also considered to be the first practice of the new version of DjangoStarter, so I encountered some pitfalls, I have written a blog record!
- Using pdm to manage dependencies in the docker image of a python project
- New version of Django Docker deployment solution with multi-stage builds, automated front-end dependency handling
- Problems with using python-slim mirrors that do not work with PostgreSQL
Overall daphne servers are working fine.
wrap-up
As I said at the beginning, this project is relatively simple, the time is mainly spent on the front-end interaction and some details of the adjustment
Taro is a silky-smooth way to develop applets, and none of the expected problems with packaging and publishing were actually encountered.
This little summary has really been dragging on for too long, and I haven't written code in a while... gotta catch up on organizing my thoughts, and then messing around with whatever I want to do.