I have this simple model and I am having difficult in inserting related field of 'notes' through django rest framework.
class Student(models.Model):
firstName = models.CharField(max_length=100, blank=True, null=True)
lastName = models.CharField(max_length=100, blank=True, null=True)
prefLocation = models.ManyToManyField("Location", blank=True, null=True, related_name = 'prefLocation')
def __unicode__(self):
return self.firstName
class LocationRegion(models.Model):
regionName = models.CharField(max_length=100)
def __unicode__(self):
return self.regionName
class Location(models.Model):
locationName = models.CharField(max_length=100)
region = models.ForeignKey(LocationRegion, null=True, blank=True, related_name='locations')
def __unicode__(self):
return self.locationName
class Note(models.Model):
text = models.CharField(max_length=1000)
student = models.ForeignKey(Student, null=True, blank=True, related_name='notes')
def __unicode__(self):
return self.text
class StudentViewSet(viewsets.ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentSerializer
I am unsure if I need to use ModelSerializer or generic Serializer. Validated_data doesn't return 'note' field in the deserialized data. I would appreciate any help with the serializer.
Thanks
Here are my serializers :
class StudentSerializer(serializers.ModelSerializer):
def create(self, validated_data):
def get_notes(self, obj):
return validated_data['note']
note = serializers.SerializerMethodField('get_notes')
return Candidate.objects.create(**validated_data)
class Meta:
model = Student
fields = ('id', 'firstName', 'lastName', 'note')
class NoteSerializer(serializers.ModelSerializer):
class Meta:
model = Note
Related
I have 4 related models and I need to implement the functionality to consistently create instances of these models in a database in one post query. For this I use override of the APIView class post method.
models
class VendorContacts(models.Model):
contact_id = models.AutoField(primary_key=True)
vendor = models.OneToOneField('Vendors', on_delete=models.CASCADE)
contact_name = models.CharField(max_length=45, blank=True)
phone = models.CharField(max_length=45, blank=True)
email = models.CharField(max_length=80, blank=True, unique=True)
class Meta:
db_table = 'vendor_contacts'
class VendorModuleNames(models.Model):
vendor = models.OneToOneField('Vendors', on_delete=models.CASCADE, primary_key=True)
module = models.ForeignKey(Modules, models.DO_NOTHING)
timestamp = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'vendor_module_names'
unique_together = (('vendor', 'module'),)
class Vendors(models.Model):
COUNTRY_CHOICES = tuple(COUNTRIES)
vendorid = models.AutoField(primary_key=True)
vendor_name = models.CharField(max_length=45, unique=True)
country = models.CharField(max_length=45, choices=COUNTRY_CHOICES)
nda = models.DateField(blank=True, null=True)
user_id = models.ForeignKey('c_users.CustomUser', on_delete=models.PROTECT)
timestamp = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'vendors'
unique_together = (('vendorid', 'timestamp'),)
class Modules(models.Model):
MODULES_NAME =tuple(MODULES)
mid = models.AutoField(primary_key=True)
module_name = models.CharField(max_length=50, choices=MODULES_NAME)
active = models.BooleanField(default=True)
timestamp = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'modules'
unique_together = (('mid', 'timestamp'),)
serializer.py
class VendorsSerializer(serializers.ModelSerializer):
class Meta:
model = Vendors
fields = ('vendor_name',
'country',
'nda',)
class VendorContactSerializer(serializers.ModelSerializer):
class Meta:
model = VendorContacts
fields = (
'contact_name',
'phone',
'email',)
class VendorModulSerializer(serializers.ModelSerializer):
class Meta:
model = VendorModuleNames
fields = ('module',)
class ModulesSerializer(serializers.ModelSerializer):
class Meta:
model = Modules
fields = ('module_name', )
views.py
class VendorsCreateView(APIView):
"""Create new vendor instances from form"""
def post(self, request, *args, **kwargs):
vendor_serializer = VendorsSerializer(data=request.data)
vendor_contact_serializer = VendorContactSerializer(data=request.data)
vendor_modules_serializer = VendorModulSerializer(data=request.data)
module_serializer = ModulesSerializer(data=request.data)
try:
vendor_serializer.is_valid(raise_exception=True) \
and vendor_contact_serializer.is_valid(raise_exception=True) \
and vendor_modules_serializer.is_valid(raise_exception=True) \
and module_serializer.is_valid(raise_exception=True)
vendor_serializer.save(user_id=request.user)
# ....
# Some new logic here ????
# ...
except ValidationError:
return Response({"errors": (vendor_serializer.errors,
vendor_contact_serializer.errors,
vendor_modules_serializer.errors
)},
status=status.HTTP_400_BAD_REQUEST)
else:
return Response(request.data, status=status.HTTP_200_OK)
There is no problem saving one Vendor model, but I can't imagine how to save cascading all related models in a single request.
save returns the newly saved object, which you can then pass into the subsequent save() methods:
vendor = vendor_serializer.save(user_id=request.user)
module = module_serializer.save()
vendor_module = vendor_modules_serializer.save(module=module, vendor=vendor)
vendor_contact = vendor_contact_serializer.save(vendor=vendor)
I have a created Django-CMS Plugin with a ManytoManyField to another model. When creating the Plugin on the Front-End, i want the user to be able to filter the ManytoManyField list (which might be too long).
By the way this future is already on Django admin:
class ModelAdmin(admin.ModelAdmin):
list_filter = ('field_name', )
form = PartnerLogoTableForm
Is it possible to have something similar like that on my
cms_plugins.py:
class PartnerLogoTablePlugin(CMSPluginBase):
model = LogoTablePlugin
form = LogoTablePluginForm
name = _('LogoTable Plugin')
render_template = False
search_fields = ('description',)
def render(self, context, instance, placeholder):
self.render_template = 'aldryn_logo_tables/plugins/%s/logotable.html' % instance.style
context.update({
'object': instance,
'placeholder': placeholder,
})
return context
plugin_pool.register_plugin(PartnerLogoTablePlugin)
models.py:
class PartnerLogoTable(models.Model):
name = models.CharField(_('Partner name'), max_length=255)
image = FilerImageField(verbose_name=_('Image'), null=True, blank=True, on_delete=models.SET_NULL)
partner_url = models.TextField(_('Partner url'), null=True, blank=True, validators=[URLValidator()])
is_active = models.BooleanField(_('Is active'), blank=True, default=True)
created_at = models.DateTimeField(_('Created at'), auto_now_add=True)
updated_at = models.DateTimeField(_('Updated at'), auto_now=True)
order = models.IntegerField(_('Order'), null=True, blank=True)
class Meta:
verbose_name = _('Partner Logo')
verbose_name_plural = _('Partner Logos')
ordering = ['order']
def __str__(self):
return self.name
class LogoTablePlugin(CMSPlugin):
DEFAULT = 'default'
LOGOTABLE_CHOICES = [
(DEFAULT, _('Default')),
]
description = models.CharField(_('Description'), max_length=255, null=True, blank=True)
partner = models.ManyToManyField(PartnerLogoTable, verbose_name=_('Partner'))
logo_per_row = models.IntegerField(_('Logo per line'), default=1, null=True, blank=True,
validators=[MaxValueValidator(4), MinValueValidator(1)],
help_text=_('Number of logos to be displayed per row'))
style = models.CharField(_('Style'), choices=LOGOTABLE_CHOICES + get_additional_styles(), default=DEFAULT,
max_length=50, blank=True, null=True, )
class Meta:
verbose_name = _('Partner Logo Plugin')
verbose_name_plural = _('Partner Logo Plugins')
def __unicode__(self):
return u'%s' % self.description
forms.py
class LogoTablePluginForm(forms.ModelForm):
model = LogoTablePlugin
def clean_style(self):
.....
return style
class PartnerLogoTableForm(forms.ModelForm):
model = PartnerLogoTable
def clean(self):
....
return self.cleaned_data
This is how the plugin looks now
ModelSelect2Multiple from django-autocomplete-light seems perfect for your use case.
I have two models:
class Album(models.Model):
code = models.CharField(max_length=10, primary_key=True, default=_create_access_code, verbose_name=_("Id"))
name = models.CharField(max_length=200, verbose_name=_("Name"))
description = models.TextField(null=True, blank=True, verbose_name=_("Description"))
company = models.ForeignKey(Company, on_delete=models.PROTECT, related_name='albums', verbose_name=_("Company"))
access_code = models.CharField(max_length=10, default=_create_access_code, verbose_name=_("Internal Use"))
class Meta:
verbose_name = _("Album")
verbose_name_plural = _("Albums")
def __str__(self):
return "[{}] {} ({})".format(self.pk, self.name, self.company.id)
class Photo(models.Model):
name = models.CharField(max_length=100, null=True, blank=True, verbose_name=_("Name"))
album = models.ForeignKey(Album, on_delete=models.CASCADE, related_name='photos', verbose_name=_("Album"))
photo = models.ImageField(verbose_name=_("Photo"))
class Meta:
verbose_name = _("Photo")
verbose_name_plural =_("Photos")
def __str__(self):
return "[{}] {}".format(self.pk, self.name)
I am trying to make a post to the ModelViewSet for model Albums, but I get an error indicating that field photos is required. Even the OPTIONS method indicates it es required.
How can I instruct DRF for not considering look up fields as required? Is it some serializer setting?
You can add required=False to fields in the serializer.
photos = PhotoSerializer(many=True, required=False)
Something like this. Can you post you serializers?
I'm getting a "'Document' object is not iterable" error when this form is submitted. It works if 'document' is just taken from the model rather than written with the select2 package. It's extremely similar to the example code from the django_select2 package. I've tried making it Document.objects.all() instead, and that didn't work either.
models.py
class Individual(models.Model):
id = models.CharField(max_length=8, unique=True, verbose_name='ID')
first_name = models.CharField(max_length=50, null=True)
middle_name = models.CharField(max_length=50, blank=True, null=True)
last_name = models.CharField(max_length=100, null=True)
dob = models.CharField(max_length=15, blank=True)
suffix = models.CharField(max_length=25, blank=True, null=True)
time_stamp = models.DateTimeField(auto_now=True)
entered_by = models.CharField(max_length=50)
def _name(self):
return self.first_name + ' ' + self.last_name
class Meta:
db_tablespace = 'name_of_database'
def __unicode__(self):
return self.id
class Document(models.Model):
document_name = models.CharField(max_length=100)
class Meta:
db_tablespace = 'name_of_database'
def __unicode__(self):
return self.document_name
class DocLog(models.Model):
individual = models.ForeignKey('Individual', to_field='id', null=True)
fiscal = models.PositiveIntegerField(db_index=True)
document = models.ManyToManyField(Document, max_length=50,
verbose_name='Document Title')
date_received = models.DateField(editable=True, verbose_name='Date Received')
doc_notes = models.TextField(max_length=500, verbose_name='Document Notes')
time_stamp = models.DateTimeField(auto_now=True)
entered_by = models.CharField(max_length=50)
class Meta:
db_tablespace = 'name_of_database'
verbose_name = 'Document Log'
def __unicode__(self):
return self.individual.id
forms.py
from django import forms
from django_select2 import *
from .models import DocLog, Document
#Document Select2 class
class DocumentChoices(AutoModelSelect2Field):
queryset = Document.objects
search_fields = ['document_name__icontains',]
#New document form
class NewDocument(forms.ModelForm):
document = DocumentChoices()
class Meta:
model = DocLog
fields = ('individual', 'fiscal', 'document', 'date_received', 'doc_notes')
widgets = {
'individual': forms.HiddenInput(),
}
You defined ManyToManyField in your Model, in Modelform ManyToManyField is represented by django.forms.ModelMultipleChoiceField, which is a MultipleChoiceField whose choices are a model QuerySet.
So instead of using AutoModelSelect2Field you use AutoModelSelect2MultipleField
for your case
#Document Select2 class
class DocumentChoices(AutoModelSelect2MultipleField):
queryset = Document.objects
search_fields = ['document_name__icontains',]
I have these three models namely:
ButuanMaps, Owner, LandProperty
class ButuanMaps(gismodel.Model):
class Meta:
verbose_name = u'Butuan Map'
verbose_name_plural = u'Butuan Maps'
clandpin = gismodel.CharField("Land PIN", max_length=50,
null=True, blank=True)
ssectionid = gismodel.ForeignKey(Section)
#ssectionid_id = gismodel.IntegerField()
geom = gismodel.MultiPolygonField("Geom ID", srid=32651,
null=True, blank=True)
objects = gismodel.GeoManager()
def __unicode__(self):
return self.clandpin
class LandProperty(models.Model):
DEFAULT_OWNER_ID = 5
class Meta:
verbose_name = u'Land Property'
verbose_name_plural = u'Land Properties'
ctaxdec = models.CharField("Tax Declaration", max_length=50,
null=True, blank=True)
sgeomid = models.ForeignKey(ButuanMaps)
def __unicode__(self):
return self.sgeomid.clandpin
class Owner(models.Model):
user= models.OneToOneField(User)
spersonid = models.ForeignKey(Information)
User.profile = property(lambda u: Owner.objects.get_or_create(user=u)[0])
def __unicode__(self):
return self.spersonid.cfirstname
I want to get all the geom from ButuanMaps based on Owner and also get the information in every geom from LandProperty model. I tried this queryset but fail:
ButuanMaps.objects.filter(ssectionid=5).select_related('landproperty__owner')