I am using Django with Django Rest Framework for serializers.
I have the following situation.
In file models.py:
from django.db.models import Manager, Model, CharField
from .serializers import MyModelSerializer
class MyModelManager(Manager):
serializer_class = MyModelSerializer
class MyModel(Model):
name = CharField(max_length=64)
objects = MyModelManager()
In file serializers.py:
from rest_framework.serializers import ModelSerializer
from models import MyModel
class MyModelSerializer(ModelSerializer):
class Meta:
model = MyModel
fields = ('name',)
However, this leads to an import cycle, since both files try to import each other. I could prevent this by making a local import:
class MyModelManager(Manager):
#property
def serializer_class(self):
from ow_articlecode.import_cycle_serializers import MyModelSerializer
return MyModelSerializer
However, this feels like a hack. What would be a proper solution to break this import cycle?
A Manager [Django-doc], has no serializer_class field. In fact a manager does not know anything about serialization. A manager is used to filter, create, etc. objects.
Your models.py thus should look like:
# app/models.py
from django.db.models import Manager, Model, CharField
class MyModelManager(Manager):
# no serializer_class
pass
class MyModel(Model):
name = CharField(max_length=64)
The idea of Models is that this defines your business logic, not the serialization, form, view, template logic.
i'm new to django. The version i'm using is 1.11.2
I have a a schema like this.
There are many "designs" and each design can have any number of "patterns".
my design model is like below
from django.db import models
from products.models import Product
class Design(models.Model):
name = models.CharField(max_length=200)
product_id = models.ForeignKey(Product, on_delete=models.CASCADE)
price = models.CharField(max_length=200)
def __str__(self):
return self.name
My design serializer is like below
from rest_framework import serializers
from .models import Design
from rest_framework import serializers
from patterns.models import Pattern
class DesignsSerializer(serializers.ModelSerializer):
patterns = DesignPatternSerializer(read_only=True, many=True)
class Meta:
depth = 1
model = Design
fields = ('id','name','patterns')
read_only_fields = ('id','name','patterns')
The view for designs is as below
from django.shortcuts import render
from .models import Design
from .serializers import DesignsSerializer
from rest_framework import generics, filters
# Create your views here.
class ListDesignsByProducId(generics.ListCreateAPIView):
serializer_class = DesignsSerializer
def get_queryset(self):
return Design.objects.filter(product_id__exact = self.kwargs.get('product_id'))
My pattern model is like below.
from django.db import models
from datetime import date
from designs.models import Design
class Pattern(models.Model):
design_id = models.ManyToManyField(Design)
name = models.CharField(max_length=200)
def __str__(self):
return self.name
My pattern serializer is as below
from rest_framework import serializers
from .models import Pattern
class PatternSerializer(serializers.ModelSerializer):
class Meta:
depth = 1
model = Pattern
fields = ('id','design_id','name')
read_only_fields =('id','design_id','name')
Right now the api would return the details of the designs and it's associated products.
I would also like to get an array of patterns associated with the design.
In your DesignsSerializer you referred to the patterns by the name patterns without defining it in your models.
From the Django REST Framework documentation:
You'll normally want to ensure that you've set an appropriate
related_name argument on the relationship, that you can use as the
field name.
In your Pattern model:
class Pattern(models.Model):
design_id = models.ManyToManyField(Design, related_name='patterns')
...
I need to make a page that can save a lot of students information for example when we want to add a new user/student we should enter some required field..actually I can add and save a name,last name,NO, etc...but I can't save a many lessons for one student like this picture.
my page
what I want is a view for my project . I try a lot Algorithm but I can't save to data base / admin page.
my admin.py
from django.contrib import admin
from .models import Students
class StudentsAdminInline(admin.TabularInline):
model =Students
class StudentsAdmin(admin.ModelAdmin):
list_display = ["__str__","o_no","f_name","l_name","University","date","timestamp","update"]
inlines = [StudentsAdminInline]
admin.site.register(Students)
my model.py
from django.db import models
class Students (models.Model):
email=models.EmailField()
f_name=models.CharField(default="",max_length=50)
l_name = models.CharField(default="",max_length=50,blank=False)
o_no=models.CharField(default="",null=False,max_length=50)
University=models.CharField(default="",max_length=50)
date=models.DateField(editable=True,null=True)
timestamp=models.DateTimeField(auto_now_add=True,auto_now=False)
update=models.DateTimeField(auto_now_add=False,auto_now=True)
def __str__(self):
return '{}'.format(self.id)
class Student (models.Model):
student=models.ForeignKey(Students,related_name='items')
Lessons=models.CharField(default="",max_length=50,blank=False)
Code=models.DecimalField(max_digits=2, decimal_places=1,null=True)
Success=models.CharField(default="",max_length=50,blank=False)
def __str__(self):
return '{}'.format(self.id)
my forms.py
class students_form_admin(forms.ModelForm):
class Meta:
model=Students
fields=["__str__","o_no","f_name","l_name","University","date","timestamp","update"]
class student_form_admin(forms.ModelForm):
class Meta:
model=Student
fields=["Lessons","Code","Success"]
You will need to use Django Formsets. Take a loot at Django Formsets.
Or if you want to use only django admin, you should change your code to:
admin.py:
from django.contrib import admin
from .models import Student, Lesson
class StudentAdminInline(admin.TabularInline):
model =Lesson
#admin.register(Student)
class StudentAdmin(admin.ModelAdmin):
list_display = ["__str__","o_no","f_name","l_name","University","date","timestamp","update"]
inlines = [StudentAdminInline]
models.py:
from django.db import models
class Student (models.Model):
email=models.EmailField()
f_name=models.CharField(default="",max_length=50)
l_name = models.CharField(default="",max_length=50,blank=False)
o_no=models.CharField(default="",null=False,max_length=50)
University=models.CharField(default="",max_length=50)
date=models.DateField(editable=True,null=True)
timestamp=models.DateTimeField(auto_now_add=True,auto_now=False)
update=models.DateTimeField(auto_now_add=False,auto_now=True)
def __str__(self):
return '{}'.format(self.id)
class Lesson (models.Model):
student=models.ForeignKey(Student,related_name='items')
name=models.CharField(default="",max_length=50,blank=False)
Code=models.DecimalField(max_digits=2, decimal_places=1,null=True)
Success=models.CharField(default="",max_length=50,blank=False)
def __str__(self):
return '{}'.format(self.id)
forms.py:
from .models import Student, Lesson
class students_form_admin(forms.ModelForm):
class Meta:
model=Student
fields=["__str__","o_no","f_name","l_name","University","date","timestamp","update"]
class student_form_admin(forms.ModelForm):
class Meta:
model=Lesson
fields=["Lessons","Code","Success"]
Alright, so I'm going to suggest that you read through how to create a view. The Django website has a lot of information that is incredible helpful. Here is the documentation for creating views.
As for saving to a database. Here is the documentation on setting up and using databases with your project. This link will show you how to use models and objects to save data from your view.
The Django website has all kinds of information that can help you.
I have:
class ProfileSerializer(serializers.ModelSerializer):
relevence = ??
The thing is I want to call relevance as a separate function.
I do not want to write it as a serializer method field nor under a model, can it be done?
from django.contrib.auth.models import User
from django.utils.timezone import now
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
days_since_joined = serializers.SerializerMethodField()
class Meta:
model = User
def get_days_since_joined(self, obj):
return (now() - obj.date_joined).days
Ok. do it like
class ProfileSerializer(serializers.ModelSerializer):
relevence = min(1,2,3,4) #user inbuilt `min`
But the thing is, function will execute one time only. That means when defining of class happens.
class Model1(models.Model):
name = models.CharField(...)
...
class Model2(models.Model)
model = models.OneToOneField(Model1)
...
I go to the admin panel. page add an entry to Model2, watch list model. And there all the records from Model1.
Is it possible to customize the admin area so that the list did not get records that already have a relationship.
thank you
You Should override _init_ method of form class.
You can take help from below given code.
from django import forms
from .models import Model2, Model1
class Model2Form(forms.ModelForm):
model1 = forms.ModelChoiceField(queryset=[],)
class Meta:
model = Model1
def __init__(self, *args, **kwargs):
""" initialize form data """
super(Model2Form, self).__init__(*args, **kwargs)
model2_obj = Model2.objects.all().values_list('model1')
model2_list = [data[0] for data in model2_obj]
self.fields['model1'].queryset = Model1.objects.exclude(id__in=model2_list)
In admin.py.
from django.contrib import admin
from .forms import Model2Form
from .models import Model2
class Model2Admin(admin.ModelAdmin):
form = Model2Form
fields = ['model1']
admin.site.register(Model2, Model2Admin)