django中创建多对多对应关系的异同点及如何通过外键正反向查找(双下划线使用)及Model中的一些技巧

-----------------添加学习用户---------------------

在model中定义方法

(该方法如果想在模板语言中使用,不能传递参数,因为模板语言是没有括号的,可以写self.usercourse_set.all().count()来计算总数)

class Course(models.Model):
	。。。
    def get_user(self):
        return self.usercourse_set.all()   # 外键反向查找

课程和用户之间的多对多表

class UserCourse(models.Model):
    """在用户点击了学习之后,则记录为用户学习的课程即该model的用户课程"""
    user = models.ForeignKey(UserProfile,verbose_name=u"用户")
    course = models.ForeignKey(Course,verbose_name=u"课程")

点击开始学习之后,那么该用户就会收藏该课程,要在前端显示该课程的用户,在views中

learn_stds = Course.objects.get(id=course_id).get_user()[:3]

前端写:

{% for obj in learn_stds %}
<span class="pic"><img width="40" height="40" src="{{ MEDIA_URL }}{{ obj.user.image }}"/></span>
{% endfor %}

 

 

 

-----------------添加学习用户---------------------


外键正向查找

model

class Course(models.Model):
    course_org = models.ForeignKey(CourseOrg,verbose_name=u"课程机构",blank=True,null=True)
    name = models.CharField(max_length=100,verbose_name=u"课程名")
class Lesson(models.Model):
    course = models.ForeignKey(Course,verbose_name=u"课程")
    name = models.CharField(max_length=100,verbose_name=u"章节名")

views

>>>Lesson.objects.filter(course__name=u"python进阶教程")     
[<Lesson: Lesson object>, <Lesson: Lesson object>, <Lesson: Lesson object>]

 

外键反向查找

>>>CourseOrg.objects.get(id=2).course_set.all()   # course_set中的course是表course的小写,这样就把id=1的全部Course的记录全部查出来
[<Course: python进阶教程>, <Course: java高阶>, <Course: python入门>, <Course: python高阶>, <Course: java入门>, <Course: mysql入门>, <Course: java进阶>]

 

在下面的正向查询中如果是要用到id,那么单双下划线都可以的Lesson.object.filter(course_id=1) / Lesson.object.filter(course__id=1)

反向查询还有中方法,通过related_name进行查询

class Student(models.Model):

   city = models.ForeignKey(City,verbose_name=u'学生所在城市',null=True,blank=True,related_name='inCity')

此时,就可以通过 City.objects.get(id=1).inCity.all() 这是不能通过City.objects.get(id=1).student_set.all()进行查询。

 

 

 

 

 

获取Choices中的值

degree = models.CharField(choices=(("gj",u"高级"),("zj",u"中级"),("cj",u"低级")),max_length=2,verbose_name=u"难度")

前端

{{ obj.get_degree_display }}

{{ obj.degree }}

多对多关系异同点:

Business表

首先,有一张记录了所有机器的的主机表。(foreignkey是多对一关系:就是说business中的运维部可以对应多个机器

class Host(models.Model):
    nid = models.AutoField(primary_key=True)
    hostname = models.CharField(max_length=32,db_index=True)
    ip = models.GenericIPAddressField(protocol="ipv4",db_index=True)
    port = models.IntegerField()
    b = models.ForeignKey(to="Business", to_field='id')

在表中添加数据

假如,我们有这样一个需求,公司需要把正在生产app的主机关联上各自的app项目(可能一台机器正在生产一个app项目,也可能多台机器生产一个app项目,也可能一台机器生产多个app项目),这样我们就需要有一张表来对应多对多关系。

创建多对多关系表一般有2种方式:

方法一:自定义关系表

class Application(models.Model):
     name = models.CharField(max_length=32)

class HostToApp(models.Model):
     hobj = models.ForeignKey(to='Host',to_field='nid')
     aobj = models.ForeignKey(to='Application',to_field='id')

通过HostToApp将Application和Host关联起来

但是这样创建有个坏处就是可以重复写。但实际情况是不需要主机1对应app1,主机1对应app1写2次。所以写的时候要注意。好处就是,这样创建你不仅可以关联host的nid,也可以关联hostname,管理程度更大。

nobj = models.ForeignKey(to='Host',to_field='hostname')

方法二:自动创建关系表

class Applicate(models.Model):
    name = models.CharField(max_length=32)
    r = models.ManyToManyField("Host")

这样创建的时候,会自动生成一张applicate_r的表用于关联,在这张表中无法写1-3,1-3 两次。缺点是表中只能id对应id

通过方式2要操作这样表需要通过这个r接口来操作

obj = Application.objects.get(id=1)

# 第三张表操作
obj.r.add(1)
obj.r.add(2)
obj.r.add(2,3,4)   // obj.r.add(*[1,2,3,4]) // obj.r.set([3,5,7])

obj.r.remove(1)
obj.r.remove(2,4) // obj.r.remove(*[1,2,3])

obj.r.clear()

# 所有相关的主机对象“列表” QuerySet
obj = models.Applicate.objects.get(id=2)
obj.r.all()  : <QuerySet [<Host: Host object>, <Host: Host object>, <Host: Host object>]>,获取到了host对象,我们就可以取到host的值了

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Django,如果一个模型表有多个外键,那么在创建序列化器时,需要使用嵌套序列化器来处理这些外键关系。 具体来说,你可以在主要的序列化器使用`serializers.SerializerMethodField`字段,并定义一个自定义的方法来嵌套序列化每个外键关系。 例如,假设你有一个`Book`模型,它有一个`author`字段和一个`publisher`字段,它们都是外键关系。你可以创建一个名为`BookSerializer`的序列化器,并在其使用嵌套序列化器来处理这两个外键关系,如下所示: ```python from rest_framework import serializers from .models import Book, Author, Publisher class AuthorSerializer(serializers.ModelSerializer): class Meta: model = Author fields = '__all__' class PublisherSerializer(serializers.ModelSerializer): class Meta: model = Publisher fields = '__all__' class BookSerializer(serializers.ModelSerializer): author = serializers.SerializerMethodField() publisher = serializers.SerializerMethodField() class Meta: model = Book fields = '__all__' def get_author(self, obj): author = obj.author return AuthorSerializer(author).data def get_publisher(self, obj): publisher = obj.publisher return PublisherSerializer(publisher).data ``` 在上面的代码,`BookSerializer`的`author`和`publisher`字段都使用了`SerializerMethodField`,并定义了`get_author`和`get_publisher`方法来进行嵌套序列化。 这样,当你使用`BookSerializer`来序列化`Book`对象时,它将自动嵌套序列化`author`和`publisher`对象,并将它们作为嵌套的JSON对象返回给你的API接口。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值