更改模型视图集中的数据
restframework-datachange的Python项目详细描述
restframewramewatachange是rest_框架的一个增强。要使用它,我们必须对django和rest_框架有基本的理解。
一。安装
像往常一样,使用pip:
$ pip install restframework_datachange
$ pip install django
$ pip install djangorestframework
2.在使用restframework_datachange之前
我们制作了一个示例restframework支持项目。
$ django-admin startproject my_project
my_project$ cd my_project
my_project$ django-admin startapp movie
现在我们按如下方式编写文件:
制作模型。
my_project/movie/models.py
fromdjango.dbimportmodelsclassCast(models.Model):SEX_CHOICE=((1,"Male"),(2,"Female"))sex=models.IntegerField(choices=SEX_CHOICE,default=1)profession=models.CharField(max_length=100,default="")foreign_name=models.CharField(max_length=100,default="")def__str__(self):returnself.foreign_nameclassOneMovie(models.Model):COUNTRY_CHOICE=((1,"UK"),(2,"US"))name=models.CharField(max_length=200,default="")director=models.ManyToManyField(Cast,related_name="director")actors=models.ManyToManyField(Cast,related_name="actors")country=models.IntegerField(default="",choices=COUNTRY_CHOICE)def__str__(self):returnself.name
生成序列化程序。有关SlugRelatedField
的用法,请参阅the document of djangorestframework。
my_project/movie/serializers.py
fromrest_framework.serializersimportModelSerializer,SlugRelatedFieldfrommovie.modelsimportOneMovie,CastclassMovieSerializer(ModelSerializer):director=SlugRelatedField(slug_field="foreign_name",queryset=Cast.objects.all(),many=True)actors=SlugRelatedField(slug_field="foreign_name",queryset=Cast.objects.all(),many=True)classMeta:model=OneMoviefields="__all__"
查看
my_project/movie/views.py
fromdjango.shortcutsimportrenderfromrest_framework.viewsetsimportModelViewSetfrommovie.modelsimportOneMoviefrommovie.serializersimportMovieSerializerclassMovieViewSet(ModelViewSet):queryset=OneMovie.objects.all()serializer_class=MovieSerializer
更改设置
我的项目/我的项目/设置.py
...INSTALLED_APPS=["django.contrib.admin","django.contrib.auth","django.contrib.contenttypes","django.contrib.sessions","django.contrib.messages","django.contrib.staticfiles","rest_framework",#"movie"#]...
进行迁移和迁移。
my_project/my_project $ cd ..
my_project $ python manage.py makemigrations
Migrations for 'movie':
movie/migrations/0001_initial.py
- Create model Cast
- Create model OneMovie
my_project$ python3 manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, movie, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying movie.0001_initial... OK
Applying sessions.0001_initial... OK
为整个项目创建URL。
my_project/my_project/url.py
fromdjango.contribimportadminfromdjango.urlsimportpathfromrest_frameworkimportroutersfrommovie.viewsimportMovieViewSeturlpatterns=[path("admin/",admin.site.urls),]router=routers.DefaultRouter()router.register(r"movie",MovieViewSet,base_name="movie")urlpatterns+=router.urls
现在我们为数据库创建一些数据。
my_project$pythonmanage.pyshellIn[1]:frommovie.modelsimportOneMovieIn[2]:frommovie.modelsimportCastIn[3]:daniel=Cast.objects.create(sex=1,profession="actor",foreign_name="Daniel")In[4]:danielOut[4]:<Cast:Daniel>In[5]:emma=Cast.objects.create(sex=2,profession="actor",foreign_name="Emma")In[6]:Cast.objects.all()Out[6]:<QuerySet[<Cast:Daniel>,<Cast:Emma>]>In[7]:david=Cast.objects.create(sex=1,profession="director",foreign_name="David")In[8]:harry_potter_movie=OneMovie.objects.create(name="Harry Potter and the Goblet of Fire",country=2)In[9]:harry_potter_movie.director.add(david)In[10]:harry_potter_movie.actors.add(daniel)In[11]:harry_potter_movie.actors.add(emma)In[12]:harry_potter_movie.save()In[13]:harry_potter_movieOut[13]:<OneMovie:HarryPotterandtheGobletofFire>In[14]:harry_potter_movie.director.all()Out[14]:<QuerySet[<Cast:David>]>In[15]:harry_potter_movie.actors.all()Out[16]:<QuerySet[<Cast:Daniel>,<Cast:Emma>]>In[16]:exit()
现在我们运行服务器。
my_project $ python manage.py runserver 0.0.0.0:8000
启动浏览器并输入http://127.0.0.1:8000/
,单击"movie": "http://127.0.0.1:8000/movie/"
塔达!一切看起来都很完美。下面是你将看到的。
[
{
"id": 1,
"director": [
"David"
],
"actors": [
"Daniel",
"Emma"
],
"name": "Harry Potter and the Goblet of Fire",
"country": 2
}
]
三。更改数据
我们只希望电影"name"
是"Harry"
,而不是"Harry Potter and the Goblet of File"
。也就是说,我们要更改返回的数据。这时restframework_datachange出现了!
my_project/movie/views.py
fromrestframework_datachange.viewsetsimportRModelViewSet# frommovie.modelsimportOneMoviefrommovie.serializersimportMovieSerializerclassMovieAdjust(object):# defchange_name(self,value):# xx = namereturnvalue.split(" ")[0]# classMovieViewSet(MovieAdjust,RModelViewSet):# queryset=OneMovie.objects.all()serializer_class=MovieSerializer
通过向Adjust
对象添加change_xx
,并将继承更改为RModelViewSet
,我们将返回的"name"
字段的值从"Harry Potter and the Goblet of File"
更改为"Harry"
!
[
{
"id": 1,
"director": [
"David"
],
"actors": [
"Daniel",
"Emma"
],
"name": "Harry",
"country": 2
}
]
现在我们将"country"
代码更改为相应的国家名称:
my_project/movie/views.py
...classMovieAdjust(object):defchange_name(self,value):returnvalue.split(" ")[0]defchange_country(self,value):dic={1:"UK",2:"US"}returndic[value]...
塔达!
[
{
"id": 1,
"director": [
"David"
],
"actors": [
"Daniel",
"Emma"
],
"name": "Harry",
"country": "US"
}
]
四。基于一个字段添加新数据
我们需要一个基于数据原始字段的新字段。例如,我们希望"actors"
的字符串版本命名为"string_actors"
。
my_project/movie/views.py
...classMovieAdjust(object):string_actors_src1="actors"defchange_name(self,value):returnvalue.split(" ")[0]defchange_country(self,value):dic={1:"UK",2:"US"}returndic[value]defadd_string_actors(self,value):return", ".join(value)...
生成一个add_xx
方法,传递一个value
并对其进行修改,然后将源字段指定为xx_src1
。然后你就可以看到这个了。
[
{
"id": 1,
"director": [
"David"
],
"actors": [
"Daniel",
"Emma"
],
"name": "Harry",
"country": "US",
"string_actors": "Daniel, Emma"
}
]
四。基于两个或多个字段添加新数据
假设我们想将"country"
字段和"name"
字段连接起来形成"detail"
字段。
classMovieAdjust(object):string_actors_src1="actors"detail_src1="country"# xx = detaildetail_src2="name"# xx = detaildefchange_name(self,value):returnvalue.split(" ")[0]defchange_country(self,value):dic={1:"UK",2:"US"}returndic[value]defadd_string_actors(self,value):return", ".join(value)defadd_detail(self,*value):# xx = detailreturn", ".join([str(i)foriinvalue])
现在您可以看到:
[
{
"id": 1,
"director": [
"David"
],
"actors": [
"Daniel",
"Emma"
],
"name": "Harry",
"country": "US",
"detail": "2, Harry Potter and the Goblet of Fire",
"string_actors": "Daniel, Emma"
}
]
注意"detail"
中的"country"
部分,它是原始值2
,而不是修改值"US"
。这里,"detail"
有源字段"country"
和"name"
,所以value[0]
是"country"
字段的值,2
。而value[1]
是"name"
,"Harry Potter and the Goblet of Fire"
的值。
您也可以这样编写代码:
classMovieAdjust(object):string_actors_src1="actors"detail_src1="country"detail_src2="name"defchange_name(self,value):returnvalue.split(" ")[0]defchange_country(self,value):dic={1:"UK",2:"US"}returndic[value]defadd_string_actors(self,value):return", ".join(value)defadd_detail(self,country,name):returnstr(country)+", "+str(name)
确保self
旁边参数的数目和位置与新创建字段的src
相同。
5个。干预其他行为。
如果您碰巧知道restframework的retrieve
、create
、update
操作,您可以通过基于下表创建Adjust
对象来干预您的返回:
Actions | Modification | Method Prefix | Source Field Suffix |
---|---|---|---|
list | add a field | add | src |
list | change a field | change | -- |
retrieve | add a field | append | org |
retrieve | change a field | modify | -- |
create | add a field | attach | bir |
create | change a field | reform | -- |
update | add a field | adjoin | lch |
update | change a field | vary | -- |
例如:
http://127.0.0.1:8000/movie/1/调用retrieve
方法。
classMovieAdjust(object):string_actors_src1="actors"detail_src1="country"# xx = detail(list)detail_src2="name"# xx = detail(list)string_actors_retrieve_org1="actors"# yy = string_actors_retrieve(retrieve)defchange_name(self,value):returnvalue.split(" ")[0]defchange_country(self,value):dic={1:"UK",2:"US"}returndic[value]defadd_string_actors(self,value):return", ".join(value)defadd_detail(self,*value):# xx = detailreturn", ".join([str(i)foriinvalue])defmodify_country(self,value):dic={1:"United Kingdom",2:"United States"}returndic[value]defappend_string_actors_retrieve(self,value):# yy = string_actors_retrievereturn", ".join(value)
{
"id": 1,
"director": [
"David"
],
"actors": [
"Daniel",
"Emma"
],
"name": "Harry Potter and the Goblet of Fire",
"country": "United States",
"string_actors_retrieve": "Daniel, Emma"
}
6.显示/隐藏字段
如果要显示或隐藏字段,可以修改操作特定的_fields
和_exclude
属性。
classMovieAdjust(object):list_exclude=["actors"]
会让您:
[
{
"id": 1,
"director": [
"David"
],
"name": "Harry Potter and the Goblet of Fire",
"country": 2
}
]
classMovieAdjust(object):list_fields=["actors","name"]
会让您:
[
{
"actors": [
"Daniel",
"Emma"
],
"name": "Harry Potter and the Goblet of Fire"
}
]
7号。将python dict转换为模型
如果您有一个python dict并希望将其转换为django模型,那么可以使用modelmaker
。
model_maker(dic,file='fake_model.py',class_name='Default',name_changer=camel_to_,default_settings=None,**config)
dic
:Pythondic。
file
:模型将写入指定的文件。作为""
传递,它将只返回打印版本。
class_name
:型号。
name_changer
:将某个字符串更改为另一个字符串的方法。默认值是一个函数,它将驼峰大小写转换为下划线。
default_settings
:指定字段类型的默认属性设置的python dict。
config
:设置模型的属性。详情请参阅the documents of django。
示例:
fromrestframework_datachange.model_makerimportmodel_makerfromdatetimeimportdatetimedic={"apple":1,# IntegerField"boy":1.2,# FloatField"cat":"string",# CharField"dog":[{"json":1}],# JSONField"elephant":datetime.now(),# DatetimeField"changed":"string"}config={"apple__choices":[(1,"UK"),(2,"US")],"boy__null":True,"cat__max_length":20,"dog__verbose_name":"Dog","elephant__auto_now":True}defname_changer(string):li=["apple","boy","cat","dog","elephant"]ifstringnotinli:return"fog"returnstringprint(model_maker(dic,file="",class_name="M",name_changer=name_changer,**config))
会给你你:
fromdjango.contrib.postgres.fieldsimportJSONFieldfromdjango.dbimportmodelsclassM(models.Model):apple=models.IntegerField(verbose_name="",help_text="",null=True,choices=[(1,"UK"),(2,"US")])boy=models.FloatField(verbose_name="",help_text="",null=True)cat=models.CharField(verbose_name="",help_text="",default="",max_length=20)dog=JSONField(verbose_name="Dog",help_text="",null=True,blank=True)elephant=models.DateTimeField(verbose_name="",help_text="",auto_now=True,auto_now_add=False)fog=models.CharField(verbose_name="",help_text="",default="",max_length=64)
通过向default_settings
参数传递python dict,可以更改model_maker
的默认设置。
dic={"apple":1}# IntegerFieldprint(model_maker(dic,file="",class_name="AppleCart",default_settings={"int":{"null":True}}))
会给你:
fromdjango.dbimportmodelsclassAppleCart(models.Model):apple=models.IntegerField(null=True)
不同类型的默认设置如下:
{"int":{"verbose_name":"","help_text":"","null":True},"str":{"verbose_name":"","help_text":"","default":"","max_length":64},"datetime":{"verbose_name":"","help_text":"","auto_now":False,"auto_now_add":False},"date":{"verbose_name":"","help_text":"","auto_now":False,"auto_now_add":False},"json":{"verbose_name":"","help_text":"","null":True,"blank":True},"bool":{"verbose_name":"","help_text":"","null":True},"float":{"verbose_name":"","help_text":"","null":True}}