class PostForm(forms.ModelForm):
description = forms.CharField(widget=PagedownWidget(show_preview=False))
class Meta:
model = Post
fields = [
'title',
'image',
'video',
'description',
'public',
'tags',
]
I am trying to bypass the required field for 'video' but having difficulty doing so. Any suggestions would be appreciated.
this is my models.py, hopefully is should help with knowing how to go on this.
from django.db import models
from django.db.models import Count, QuerySet, F
from django.utils import timezone
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.core.urlresolvers import reverse
from django.db.models.signals import pre_save
from django.utils.text import slugify
from markdown_deux import markdown
from django.utils.safestring import mark_safe
from embed_video.fields import EmbedVideoField
from taggit.managers import TaggableManager
from comments.models import Comment
def upload_location(instance, filename):
return "%s/%s" %(instance.slug, filename)
class Post(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1 )
title = models.CharField(max_length=75)
slug = models.SlugField(unique=True)
video = EmbedVideoField()
image = models.ImageField(
upload_to=upload_location,
null=True,
blank=True,
width_field="width_field",
height_field="height_field")
height_field = models.IntegerField(default=0)
width_field = models.IntegerField(default=0)
description = models.TextField()
tags = TaggableManager()
public = models.BooleanField(default=False)
updated = models.DateTimeField(auto_now_add=False, auto_now=True)
created = models.DateTimeField(auto_now_add=True, auto_now=False)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("posts:detail", kwargs={"slug": self.slug})
class Meta:
ordering = ["-created", "-updated" ]
def get_markdown(self):
description = self.description
markdown_text = markdown(description)
return mark_safe(markdown_text)
#property
def comments(self):
instance = self
qs = Comment.objects.filter_by_instance(instance)
return qs
#property
def get_content_type(self):
instance = self
content_type = ContentType.objects.get_for_model(instance.__class__)
return content_type
def create_slug(instance, new_slug=None):
slug = slugify(instance.title)
if new_slug is not None:
slug = new_slug
qs = Post.objects.filter(slug=slug).order_by("-id")
exists = qs.exists()
if exists:
new_slug = "%s-%s" %(slug, qs.first().id)
return create_slug(instance, new_slug=new_slug)
return slug
def pre_save_post_receiver(sender, instance, *args, **kwargs):
if not instance.slug:
instance.slug = create_slug(instance)
pre_save.connect(pre_save_post_receiver, sender=Post)
from the docs it looks like it should support empty now since version 0.3, i would suggest trying
video = EmbedVideoField(null=True,blank=True)
the docs say it should function like a URL field, so just the standard notation should be all you need.
good luck!
Related
I'm trying to make my nested serializer to be able to process updating when I'm only updating for the parent model. The default action in drf is that the serializer cant tell if ur child model is trying to updating or create, there's a solution where you just turn off the validation, which I don't think is ideal for the database and iots implication.
I've scour about this topic for like 2 days and I think the ideal approach to this is to override the is_valid method to be able to just return the object.
Idea from :
Django REST Framework ModelSerializer get_or_create functionality
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
class MyModelSerializer(serializers.ModelSerializer):
def is_valid(self, raise_exception=False):
if hasattr(self, 'initial_data'):
# If we are instantiating with data={something}
try:
# Try to get the object in question
obj = Security.objects.get(**self.initial_data)
except (ObjectDoesNotExist, MultipleObjectsReturned):
# Except not finding the object or the data being ambiguous
# for defining it. Then validate the data as usual
return super().is_valid(raise_exception)
else:
# If the object is found add it to the serializer. Then
# validate the data as usual
self.instance = obj
return super().is_valid(raise_exception)
else:
# If the Serializer was instantiated with just an object, and no
# data={something} proceed as usual
return super().is_valid(raise_exception)
class Meta:
model = models.MyModel
The problem is whenever I try to implment I get the error:
Field 'id' expected a number but got [{'id': 18, 'title': 'aDDD', 'body': 'aDDD', 'slug': 'aDDDbabe', 'author': 1, 'question': 25}].
obj = Question.objects.get(**self.initial_data)
This code triggers it, however When I
obj = Question.answers.get(**self.initial_data)
I get 'ReverseManyToOneDescriptor' object has no attribute 'get' .
Since mine is a nested serializer I would have to find another way to make this work. Any advice where I can fix it? :(
serializers.py
from rest_framework import serializers
# https://github.com/encode/django-rest-framework/blob/3.12.4/rest_framework/serializers.py#L839
from rest_framework.fields import ( # NOQA # isort:skip
CreateOnlyDefault, CurrentUserDefault, SkipField, empty
)
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from .models import Question, Answer
class AnswerSerializer(serializers.ModelSerializer):
"""Serialize Answer model"""
class Meta:
model = Answer
fields = ('id','title', 'body', 'slug', 'author', 'question')
# https://stackoverflow.com/questions/57249850/overwriting-nested-serializers-create-method-throws-typeerror-create-got-mul
read_only_fields = ('question',)
lookup_field = 'slug'
# https://stackoverflow.com/questions/55031552/how-to-access-child-entire-record-in-parent-model-in-django-rest-framework
class QuestionSerializer(serializers.ModelSerializer):
"""Serialize Question model"""
#This answer variable and the fields 'answer' you refer to has to be the SAME but
#These can change exp: 'aaa'
answers = AnswerSerializer(read_only=False, many=True,)
class Meta:
model = Question
fields = ('id','title', 'body', 'slug', 'author', 'category', 'answers',)
lookup_field = 'slug'
def is_valid(self, raise_exception=False):
if hasattr(self, 'initial_data'):
# If we are instantiating with data={something}
try:
# Try to get the object in question
obj = Question.objects.get(**self.initial_data)
except (ObjectDoesNotExist, MultipleObjectsReturned):
print("LOLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL")
return print(obj)
else:
print("LOLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL")
print(obj)
else:
return super().is_valid(raise_exception)
def create(self, validated_data):
answers_data = validated_data.pop('answers')
question = Question.objects.create(**validated_data)
for answer_data in answers_data:
#The above stackoverflow link at the answer serializers is realted to this
Answer.objects.create(question=question, **answer_data)
return question
def update(self, instance, validated_data):
instance.title = validated_data.get('title', instance.title)
instance.body = validated_data.get('body', instance.body)
instance.slug = validated_data.get('slug', instance.slug)
instance.author = validated_data.get('author', instance.author)
instance.category = validated_data.get('category', instance.category)
instance.save()
# https://django.cowhite.com/blog/create-and-update-django-rest-framework-nested-serializers/
answers_data = validated_data.pop('answers')
aas = (instance.answers).all()
print("######")
print(aas)
print("######")
print(instance.answers.get().slug)
print("#########################################")
aas2 = list(aas)
print("######")
for f in validated_data:
print(f)
print(validated_data.items())
print(dir(validated_data))
print("######")
for answer_data in answers_data:
aas3 = aas2.pop(0)
aas3.title= answer_data.get('title', aas3.title)
aas3.body= answer_data.get('body', aas3.body)
aas3.slug= answer_data.get('slug', aas3.slug)
aas3.author= answer_data.get('author', aas3.author)
aas3.question= answer_data.get('question', aas3.question)
aas3.save()
return instance
views.py
from django.shortcuts import render
from .models import Question, Answer
from django.conf import settings
from rest_framework import viewsets
from rest_framework.authentication import TokenAuthentication
from .serializers import QuestionSerializer
#from .permissions import UpdateOwnPrice
from rest_framework.permissions import IsAdminUser
class QuestionViewSet(viewsets.ModelViewSet):
"""CRUD """
serializer_class = QuestionSerializer
queryset = Question.objects.all()
authentication_classes = (TokenAuthentication,)
#permission_classes = (UpdateOwnPrice,)
lookup_field = 'slug'
extra_kwargs = {'slug': {'validators': []},}
models.py
from django.db import models
from django.conf import settings
from django.db.models import Q
from django.utils import timezone
from django.urls import reverse
class Category(models.Model):
name= models.CharField(max_length=100)
def __str__(self):
return self.name
class Question(models.Model):
title= models.CharField(max_length= 100)
body= models.TextField()
slug= models.SlugField(unique= True)
date_posted= models.DateTimeField(default=timezone.now)
author= models.ForeignKey(settings.AUTH_USER_MODEL, on_delete= models.CASCADE, related_name = 'questions')
category= models.ForeignKey(Category, on_delete= models.CASCADE, related_name = 'questions')
#objects= QnAManager()
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('home')
class Answer(models.Model):
title= models.CharField(max_length= 100)
body= models.TextField()
slug= models.SlugField(unique= True)
date_posted= models.DateTimeField(default=timezone.now)
author= models.ForeignKey(settings.AUTH_USER_MODEL, on_delete= models.CASCADE, related_name = 'answers')
question= models.ForeignKey(Question, on_delete= models.CASCADE, related_name = 'answers')
#objects= QnAManager()
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('home')
I designed a database for my django ecommerce project but it have some problems, the goal of
the this design is to have products with different specifications for example a mobile cell has it's own properties and a television too,
it is my models.py:
'''
from django.db import models
from mptt.models import MPTTModel, TreeForeignKey
from django.shortcuts import reverse
from model_utils import FieldTracker
from . import uploaders
class Category(MPTTModel):
name = models.CharField(max_length=50, unique=True)
parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True,
related_name='children')
slug = models.SlugField(max_length=75, unique=True)
tracker = FieldTracker(fields=['name'])
class MPTTMeta:
order_insertion_by = ['name']
def __str__(self):
category_names = [self.name]
node = self
while node.parent:
node = node.parent
category_names.append(node.name)
return ' / '.join(category_names[::-1])
def get_absolute_url(self):
return reverse('product_by_category', args=(self.slug,))
class ProductType(models.Model):
name = models.CharField(max_length=50, unique=True)
def __str__(self):
return self.name
class ProductSpecifications(models.Model):
name = models.CharField(max_length=50)
product_type = models.ForeignKey(ProductType, on_delete=models.CASCADE,
related_name='specifications')
class Meta:
unique_together = ('name', 'product_type')
def __str__(self):
return self.name
class Product(models.Model):
name = models.CharField(max_length=100, unique=True)
product_type = models.ForeignKey(ProductType, on_delete=models.CASCADE,
related_name='products')
category = models.ForeignKey(Category, on_delete=models.CASCADE,
related_name='products')
price = models.PositiveBigIntegerField()
discount_price = models.PositiveBigIntegerField(null=True, blank=True)
description = models.TextField(null=True, blank=True)
image = models.ImageField(upload_to=uploaders.product_img_uploader)
slug = models.SlugField(max_length=150, unique=True)
tracker = FieldTracker(fields=['slug', 'name', 'product_type'])
def __str__(self):
return self.name
def set_discount(self, percentage):
self.discount_price = self.price * (1 - percentage)
self.save()
#property
def is_discounted(self):
return bool(self.discount_price)
def remove_discount(self):
self.discount_price = None
self.save()
class ProductSpecificationValue(models.Model):
specification = models.ForeignKey(ProductSpecifications, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE,
related_name='specifications')
value = models.CharField(max_length=75, null=True, blank=True)
def __str__(self):
return ''
class Meta:
unique_together = ('specification', 'product')
'''
And admin.py:
'''
from django.contrib import admin
from django.http import HttpResponseRedirect
from mptt.admin import MPTTModelAdmin
from .models import *
from .forms import ProductSpecForm
#admin.register(Category)
class CategoryAdmin(MPTTModelAdmin):
readonly_fields = ('slug',)
class SpecificationInline(admin.TabularInline):
model = ProductSpecifications
extra = 2
#admin.register(ProductType)
class ProductTypeAdmin(admin.ModelAdmin):
inlines = (SpecificationInline,)
class SpecificationValueInline(admin.TabularInline):
model = ProductSpecificationValue
# form = ProductSpecForm
# fields = ('specification', 'value')
# readonly_fields = ('specification',)
#
# def has_add_permission(self, request, obj):
# return False
#
# def has_delete_permission(self, request, obj=None):
# return False
#admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
inlines = (SpecificationValueInline,)
readonly_fields = ('slug',)
# def response_post_save_add(self, request, obj):
# return HttpResponseRedirect(
# reverse("admin:%s_%s_change" % (self.model._meta.app_label,
# self.model._meta.model_name), args=(obj.id,)))
'''
the problem is in product admin panel when you want to add or change a product, I want the select box for specification in SpecificationValueInline form show me only specifications related to the product type not all specifications in db, the lines that I commented in admin.py with some signals and a form was my approach to solve this issue i dont know if it was the best help me please!
signals.py:
'''
from django.dispatch import receiver
from django.db.models.signals import pre_save, post_save
from .models import Category, Product, ProductSpecificationValue, ProductSpecifications
#receiver(pre_save, sender=Product)
#receiver(pre_save, sender=Category)
def initialize_slug(sender, instance, *args, **kwargs):
if (not instance.slug) or (instance.tracker.has_changed('name')):
instance.slug = instance.name.replace(' ', '_')
#receiver(post_save, sender=Product)
def initialize_specifications(sender, instance, created, **kwargs):
if created:
product_type = instance.product_type
for specification in product_type.specifications.all():
ProductSpecificationValue.objects.create(product=instance,
specification=specification)
elif instance.tracker.has_changed('product_type'):
ProductSpecificationValue.objects.filter(product=instance).delete()
product_type = instance.product_type
for specification in product_type.specifications.all():
ProductSpecificationValue.objects.create(product=instance,
specification=specification)
#receiver(post_save, sender=ProductSpecifications)
def add_new_specs_to_related_products(sender, instance, created, **kwargs):
if created:
product_type = instance.product_type
for product in product_type.products.all():
ProductSpecificationValue.objects.create(specification=instance,
product=product)
'''
forms.py:
'''
from django import forms
from django.forms import ModelChoiceField
from .models import ProductSpecificationValue, Product
class ProductSpecForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if hasattr(self.instance, 'product'):
self.fields['specification'] = ModelChoiceField(
queryset=self.instance.product.product_type.specifications.all())
class Meta:
model = ProductSpecificationValue
fields = ('specification', 'value')
'''
you can use formfield_for_foreignkey in SpecificationValueInline
class SpecificationValueInline(admin.TabularInline):
model = ProductSpecificationValue
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "specification":
product_id = request.resolver_match.kwargs.get('object_id')
productType = Product.objects.get(id = product_id).product_type
kwargs["queryset"] = ProductSpecification.objects.filter(product_type=productType)
return super().formfield_for_foreignkey(db_field, request, **kwargs)
mohsen ma answer was usefull I made some changes and it got better but I still doubt it it is enough or best practice, if user changes the product type he/she should stay on change page to fill the specification idk how:
'''
#receiver(post_save, sender=Product)
def sync_specs_with_type(sender, instance, created, **kwargs):
if created or instance.tracker.has_changed('product_type'):
if not created:
instance.specifications.all().delete()
for spec in instance.product_type.specifications.all():
ProductSpecificationValue.objects.create(product=instance, specification=spec)
class SpecificationValueInline(admin.TabularInline):
model = ProductSpecificationValue
extra = 0
def formfield_for_foreignkey(self, db_field, request, **kwargs):
product_id = request.resolver_match.kwargs.get('object_id')
if product_id and db_field.name == "specification":
product_type = Product.objects.get(id=product_id).product_type
kwargs["queryset"] = ProductSpecifications.objects.filter(product_type=product_type)
return super().formfield_for_foreignkey(db_field, request, **kwargs)
#admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
readonly_fields = ('slug',)
inlines = (SpecificationValueInline,)
def response_post_save_add(self, request, obj):
messages.add_message(request, messages.INFO, 'set you product specifications')
return HttpResponseRedirect(
reverse("admin:%s_%s_change" % (self.model._meta.app_label, self.model._meta.model_name), args=(obj.id,)))
def get_inlines(self, request, obj):
if obj:
return super().get_inlines(request, obj)
return ()
'''
serializer.py
from rest_framework import serializers
from status.models import Status
class StatusSerializer(serializers.ModelSerializer):
class Meta:
model = Status
fields = [
'user',
'content',
'image'
]
def validate(self, data):
content = data.get('content', None)
if content == '':
content = None
image = data.get('image', None)
if content is None and image is None:
raise serializers.ValidationError('Content or image is required.')
return data
views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from status.models import Status
from .serializers import StatusSerializer
class StatusListSearchAPIView(APIView):
permission_classes = []
authentication_classes = []
def get(self, request):
qs = Status.objects.all()
serializer = StatusSerializer(qs)
print(serializer)
return Response(serializer.data)
models.py
from django.db import models
from django.conf import settings
def upload_status_image(instance, filename):
return "updates/{user}/{filename}".format(user=instance.user, filename=filename)
class StatusQuerySet(models.QuerySet):
pass
class StatusManager(models.Manager):
def get_queryset(self):
return StatusQuerySet(self.model, using=self._db)
class Status(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, )
content = models.TextField(null=True, blank=True)
image = models.ImageField(upload_to=upload_status_image, null=True, blank=True)
updated = models.DateTimeField(auto_now=True)
timestamp = models.DateTimeField(auto_now_add=True)
objects = StatusManager()
def __str__(self):
return str(self.content)[:50]
class Meta:
verbose_name = 'Status post'
verbose_name_plural = 'Status posts'
error:
AttributeError: Got AttributeError when attempting to get a value for field user on serializer StatusSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the StatusQuerySet instance.
Original exception text was: 'StatusQuerySet' object has no attribute 'user'.
In views.py
Change this line :
serializer = StatusSerializer(qs)
to this line:
serializer = StatusSerializer(qs, many=True)
My model.py:
from django.conf import settings
from django.db import models
from django.db.models.signals import pre_save, post_save
from django.urls import reverse
from django.utils.text import slugify
# Create your models here.
class Stocks(models.Model):
title = models.ForeignKey('Product', verbose_name="Ürün", on_delete=models.CASCADE)
stock = models.DecimalField(max_digits=3,decimal_places=0,default=0,verbose_name="Stok")
seller = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
price = models.DecimalField(max_digits=100,decimal_places=2,default=0.00,verbose_name="Fiyat")
def __str__(self):
return str(self.title)
class Meta:
verbose_name = "Stok"
verbose_name_plural = "Stoklar"
def upload_image_location(instance, filename):
return "%s/%s" %(instance.id, filename)
class Product(models.Model):
title = models.CharField(max_length=100,verbose_name="Başlık")
slug = models.SlugField(blank=True, unique=True)
category = models.ForeignKey('Category', null=True, blank=True, verbose_name="Kategori",on_delete=models.CASCADE)
description = models.TextField(null=True,blank=True,verbose_name="Ürün Açıklaması")
price = models.DecimalField(max_digits=100,decimal_places=2,default=0.00,verbose_name="Fiyat")
sale_price = models.DecimalField(max_digits=100,decimal_places=2,default=0.00,null=True,blank=True,verbose_name="İndirimli Fiyat")
tax = models.DecimalField(max_digits=3,default=18,decimal_places=0,verbose_name="KDV")
status = models.BooleanField(default=True,verbose_name="Aktif/Pasif")
image1 = models.FileField(blank=True,null=True,upload_to=upload_image_location,verbose_name="Vitrin Fotoğrafı")
image2 = models.FileField(blank=True,null=True,upload_to=upload_image_location,verbose_name="Galeri Fotoğrafı 1")
image3 = models.FileField(blank=True,null=True,upload_to=upload_image_location,verbose_name="Galeri Fotoğrafı 2")
image4 = models.FileField(blank=True,null=True,upload_to=upload_image_location,verbose_name="Galeri Fotoğrafı 3")
image5 = models.FileField(blank=True,null=True,upload_to=upload_image_location,verbose_name="Galeri Fotoğrafı 4")
def get_absolute_url(self):
view_name = "detail_slug"
return reverse(view_name, kwargs={"slug": self.slug})
def __str__(self):
return self.title
class Meta:
verbose_name = 'Ürün'
verbose_name_plural = 'Ürünler'
def create_slug(instance, new_slug=None):
slug = slugify(instance.title)
if new_slug is not None:
slug = new_slug
qs = Product.objects.filter(slug=slug)
exists = qs.exists()
if exists:
new_slug = "%s-%s" %(slug, qs.first().id)
return create_slug(instance, new_slug=new_slug)
return slug
def product_pre_save_reciever(sender, instance, *args, **kwargs):
if not instance.slug:
instance.slug = create_slug(instance)
pre_save.connect(product_pre_save_reciever, sender=Product)
My views.py
class ProductDetailView(LoginRequiredMixin, MultiSlugMixin, DetailView):
model = Product
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
product_name = self.object.title
data = Stocks.objects.filter(title__icontains=product_name).order_by('price')
context['stocks'] = data
return context
urls.py
from django.urls import path
from products import views
from products.views import (
CategoryCreateView,
CategoryUpdateView,
ProductCreateView,
ProductListView,
ProductDetailView,
ProductUpdateView,
)
urlpatterns = [
path('urunler/', ProductListView.as_view(), name='list'),
path('urunler/ekle/', ProductCreateView.as_view(), name='create'),
path('urunler/duzenle/<int:pk>/', ProductUpdateView.as_view(), name='update'),
path('urunler/duzenle/<slug>/', ProductUpdateView.as_view(), name='update_slug'),
path('urunler/<int:pk>/', ProductDetailView.as_view(), name='detail'),
path('urunler/<slug>/', ProductDetailView.as_view(), name='detail_slug'),
path('kategori/ekle/', CategoryCreateView.as_view(), name='add_category'),
path('kategori/duzenle/<int:pk>/', CategoryUpdateView.as_view(), name='update_category'),
path('kategori/duzenle/<slug>/', CategoryUpdateView.as_view(), name='update_slug_category'),
]
I'm trying to show related Stocks records on product detail page.
When I visit product detail page I get this error."Related Field got invalid lookup: icontains"
domain.com:8000/urunler/16 (for example)
I need to correct ProductDetailView class and get_context_data function but how :)
Any help?
You've called your fields strange names, which is confusing you. title is not a title, but a ForeignKey to the Product model, which itself has a title attribute.
This would work:
data = Stocks.objects.filter(title__title__icontains=product_name).order_by('price')
but really you should rename that field to something sensible, eg product, so that you would do product__title__icontains.
I am trying to save data from my Django Admin to my database but somehow it is not happening. I have created a form in one of my apps which my admin uses.I am new to Django and any help would be greatly appreciated.
Below is the relevant code:
models.py
from __future__ import unicode_literals
from django.contrib.auth.models import User
from django_countries.fields import CountryField
from django.db import models
class UserProfile(models.Model):
user = models.OneToOneField(User)
name = models.CharField(max_length=100)
bio = models.TextField(max_length=1000, blank=True, null=True)
image = models.FileField()
country = CountryField()
city = models.CharField(max_length=100)
twitter = models.CharField(max_length=100, null=True, blank=True)
linkedin = models.CharField(max_length=100, null=True, blank=True)
location = models.TextField()
def __unicode__(self):
return self.name
def __str__(self):
return self.name
class Mentor(models.Model):
mentor = models.CharField(max_length=100)
mentee = models.CharField(max_length=100)
def __unicode__(self):
return self.mentee
def __str__(self):
return self.mentee
forms.py
from django import forms
from models import UserProfile, Mentor
from django_countries.fields import CountryField
from django.contrib.auth.models import User
from reports.models import Reports
class UserProfileForm(forms.ModelForm):
name = forms.CharField(max_length=100)
bio = forms.Textarea()
image = forms.FileField(label='Profile Photo')
country = CountryField(blank_label='(Select Country)')
city = forms.CharField(max_length=100)
twitter = forms.CharField(max_length=100, required=False)
linkedin = forms.CharField(max_length=100, required=False)
class Meta:
model = UserProfile
exclude = ('user',)
class MentorForm(forms.ModelForm):
mentor_choices = tuple(UserProfile.objects.filter(user__is_staff=1).order_by('name').values_list('name', 'name'))
mentee_choices = tuple(UserProfile.objects.exclude(user__is_staff=1).order_by('name').values_list('name', 'name'))
mentor_name = forms.ChoiceField(choices=mentor_choices)
mentee_name = forms.ChoiceField(choices=mentee_choices)
def save(self, commit=True):
mentor_name = self.cleaned_data.get('mentor_name', None)
mentor_name = self.cleaned_data.get('mentee_name', None)
return super(MentorForm, self).save(commit=commit)
class Meta:
model = Mentor
fields= ('mentor_name', 'mentee_name')
admin.py
from django.contrib import admin
from .models import UserProfile, Mentor
from.forms import MentorForm
class UserProfileAdmin(admin.ModelAdmin):
list_display = ('user',)
search_fields = ['user']
def save_model(self, request, obj, form, change):
obj.created_by = request.user
obj.save()
admin.site.register(UserProfile, UserProfileAdmin )
class MentorAdmin(admin.ModelAdmin):
list_display = ('__unicode__','mentee')
search_fields = ['mentee', 'mentor']
form = MentorForm
fieldsets = (
(None,{
'fields': ('mentor_name', 'mentee_name'),
}),
)
def save_model(self, request, obj, form, change):
super(MentorAdmin, self).save_model(request, obj, form, change)
admin.site.register(Mentor, MentorAdmin )
The UserProfile works perfectly but the Mentor form in admin doesn't save anything in the database. It creates blank entries into the database, so I know that the front and backend are talking but no data is being passed. Any help will be very helpful
def save(self, commit=True):
# here you define `mentor_name`. OK.
mentor_name = self.cleaned_data.get('mentor_name', None)
# here you redefine `mentor_name`. I guess it is a typo and should be `mentee_name`.
mentor_name = self.cleaned_data.get('mentee_name', None)
# And... you don't do anything with these variables.
return super(MentorForm, self).save(commit=commit)
This method is equivalent to:
def save(self, commit=True):
return super(MentorForm, self).save(commit=commit)
Which is equivalent to not overriding the save method at all.
And what about this?
def save_model(self, request, obj, form, change):
super(MentorAdmin, self).save_model(request, obj, form, change)
What is the purpose of overriding a method and only calling the parent method with the exact same arguments?
But the actual issue is here:
mentor_choices = tuple(UserProfile.objects.filter(user__is_staff=1).order_by('name').values_list('name', 'name'))
mentee_choices = tuple(UserProfile.objects.exclude(user__is_staff=1).order_by('name').values_list('name', 'name'))
mentor_name = forms.ChoiceField(choices=mentor_choices)
mentee_name = forms.ChoiceField(choices=mentee_choices)
class Meta:
model = Mentor
fields = ('mentor_name', 'mentee_name')
You use a ModelForm but none of the Mentor's fields is in fields. What are you expecting this to do other than saving a row with Mentor.mentor = None and Mentor.mentee = None. You don't even mention those fields.
And why are you using CharField for Mentor.mentor and Mentor.mentee while you likely want a foreign key.
class Mentor(models.Model):
mentor = models.ForeignKey(UserProfile, models.PROTECT,
related_name='mentees')
mentee = models.ForeignKey(UserProfile, models.PROTECT,
related_name='mentors')
class MentorForm(forms.ModelForm):
class Meta:
model = Mentor
fields = ('mentor', 'mentee')
mentor = forms.ModelChoiceField(queryset=UserProfile.objects.filter(
user__is_staff=True).order_by('name'))
mentee = forms.ModelChoiceField(queryset=UserProfile.objects.exclude(
user__is_staff=True).order_by('name'))
Or even better:
class Mentor(models.Model):
mentor = models.ForeignKey(
UserProfile, models.PROTECT, related_name='mentees',
limit_choices_to={'user__is_staff': True},
)
mentee = models.ForeignKey(
UserProfile, models.PROTECT, related_name='mentors',
limit_choices_to={'user__is_staff': False},
)
Which avoids you to create a form.