how in forms.py class, overwrite the default value of the model category, without adding it to the html form?
forms.py
class FastForm(forms.ModelForm):
class Meta:
model = Orders
fields = ['device']
models.py
class Orders(models.Model):
device = models.CharField(max_length=150)
category = models.ForeignKey('Category', default=1, on_delete=models.PROTECT)
class Category(models.Model):
category = models.CharField(max_length=150, db_index=True)
UPD
views
class OrderAddView(TemplateView):
template_name = 'orders/order_add.html'
def get(self, request, *args, **kwargs):
context = super().get_context_data(**kwargs)
formOne = FastForm
context.update({'formOne': formOne})
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
formOne = FastForm(self.request.POST)
if formOne.is_valid():
form_update = formOne.save(commit=False)
form_update.save()
return HttpResponseRedirect('orders_home')
else:
print('NotValid')
Related
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 ()
'''
My models.py
from django.db import models
from django.contrib.auth.models import User
import datetime
from django.utils import timezone
# Create your models here.
class LiveClass(models.Model):
standard = models.IntegerField()
no_of_students_registered = models.IntegerField(default=0)
class Meta:
verbose_name_plural = 'Class'
def __str__(self):
return str(self.standard) + ' class'
class User_details(models.Model):
name = models.OneToOneField(User, on_delete = models.CASCADE, max_length=30)
standard = models.ForeignKey(LiveClass, on_delete=models.CASCADE)
email = models.EmailField(max_length=30)
mobile_number = models.IntegerField()
class Meta:
verbose_name_plural = 'User_details'
def __str__(self):
return self.name
class Mentor(models.Model):
name = models.CharField(max_length=30)
details = models.TextField()
ratings = models.FloatField(default=2.5)
class Meta:
verbose_name_plural = 'Mentors'
def __str__(self):
return self.name
class LiveClass_details(models.Model):
standard = models.ForeignKey(LiveClass, on_delete=models.CASCADE)
chapter_name = models.CharField(max_length=30)
chapter_details = models.TextField()
mentor_name = models.ForeignKey(Mentor, max_length=30, on_delete=models.CASCADE)
class_time = models.DateTimeField()
end_time = models.DateTimeField()
isDoubtClass = models.BooleanField(default=False)
doubtsAddressed = models.IntegerField(default=0)
class Meta:
verbose_name_plural = 'LiveClass_details'
def __str__(self):
return self.chapter_name
class SavedClass(models.Model):
class_details = models.ForeignKey(LiveClass_details, on_delete=models.CASCADE)
name = models.ForeignKey(User_details, on_delete=models.CASCADE)
is_registered = models.BooleanField(default=False)
is_attended = models.BooleanField(default=False)
class Meta:
verbose_name_plural = 'SavedClasses'
def __str__(self):
return 'SavedClass : ' + str(self.class_details)
my serializers.py
from rest_framework import serializers
from . import models
class LiveClass_serializer(serializers.ModelSerializer):
class Meta:
model = models.LiveClass
fields = '__all__'
class User_details_serializer(serializers.ModelSerializer):
class Meta:
model = models.User_details
fields = '__all__'
class LiveClass_details_serializer(serializers.ModelSerializer):
class Meta:
model = models.LiveClass_details
fields = '__all__'
class Mentor_serializer(serializers.ModelSerializer):
class Meta:
model = models.Mentor
fields = '__all__'
class SavedClass_serializer(serializers.ModelSerializer):
class Meta:
model = models.SavedClass
fields = '__all__'
my views.py
from django.shortcuts import render
from rest_framework import mixins
from rest_framework import generics
from django.contrib.auth.mixins import LoginRequiredMixin
from rest_framework import status
from django.contrib.auth.models import User
from rest_framework.response import Response
from . import serializers
from . import models
# Create your views here.
class ListLiveClass(mixins.ListModelMixin, LoginRequiredMixin, generics.GenericAPIView):
queryset = models.LiveClass_details.objects.all()
serializer_class = serializers.LiveClass_details_serializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
class LiveClassView(mixins.ListModelMixin,
mixins.CreateModelMixin,
LoginRequiredMixin,
generics.GenericAPIView):
queryset = models.LiveClass_details.objects.all()
serializer_class = serializers.LiveClass_details_serializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
if request.user.is_superuser:
return self.create(request, *args, **kwargs)
else:
return Response(status=status.HTTP_403_FORBIDDEN)
class LiveClassViewId(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
LoginRequiredMixin,
generics.GenericAPIView):
queryset = models.LiveClass_details.objects.all()
serializer_class = serializers.LiveClass_details_serializer
lookup_field = 'id'
def get(self, request, id=None, format=None):
if id:
return self.retrieve(request)
else:
return Response(status=status.HTTP_400_BAD_REQUEST)
def put(self, request, id, format=None):
if request.user.is_superuser:
return self.update(request, id)
else:
return Response(status=status.HTTP_403_FORBIDDEN)
def delete(self, request, id, format=None):
if request.user.is_superuser:
return self.destroy(request, id)
else:
return Response(status=status.HTTP_403_FORBIDDEN)
class ListMentors(mixins.ListModelMixin, LoginRequiredMixin, generics.GenericAPIView):
queryset = models.Mentor.objects.all()
serializer_class = serializers.Mentor_serializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
class ListUserDetails(mixins.ListModelMixin, LoginRequiredMixin, generics.GenericAPIView):
queryset = models.User_details.objects.all()
serializer_class = serializers.User_details_serializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
#api endpoints to save and register live classes
class SavedClassView(LoginRequiredMixin, mixins.ListModelMixin, mixins.DestroyModelMixin, generics.GenericAPIView):
model = models.SavedClass
serializer = serializers.SavedClass_serializer
def get_object(self):
return self.request.user.id
def get(self, request):
CurrentUserID = self.get_object()
In SavedClassView i want to get saved classes from the current logged user only and i want to preserve this user from getting other user saved classes , i have done something like above but i am getting no perfect logic that fits the working of django rest framework , please help me in achieving the above result
Add filter to queryset
queryset = models.User_details.objects.filter(user=request.user)
Just make sure to implement tokens so you can access request.user
I have two questions in regards to the problem I am currently facing:
Is it best practice in django to overwrite the post method in the CreateView? If it isn't do you write a form _valid function on the CategoryFullForm or in the CreateView and how would it look? The CreateView currently works great, but want to make sure there isn't a better way to do this.
If this is best practice, how would you override the get function in the UpdateView so you would be able to edit the files that relate to the instance being uploaded and even add an additional File? Open to other ways to accomplish this task as well.
models.py
############ CATEGORY MODEL ################
class Category(models.Model):
category_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100, null=True, blank=True)
est_pr_sqft = models.FloatField(blank=True)
est_duration = models.IntegerField(blank=True)
preceding_job = models.CharField(max_length=100, blank=True)
category_notes = models.CharField(max_length=250, blank=True)
category_slug = models.SlugField(max_length=100, unique=True, null=False)
author = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
date_posted = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('category-detail', kwargs={'slug': self.category_slug})
def save(self, *args, **kwargs):
if not self.category_slug:
self.category_slug = slugify(self.name)
return super().save(*args, **kwargs)
class CategoryFiles(models.Model):
category_id = models.ForeignKey(Category, on_delete=models.CASCADE)
document = models.FileField(upload_to="attachments",null=True,blank=True)
uploaded_date = models.DateTimeField(auto_now_add=True)
modified_date = models.DateTimeField(auto_now=True)
def delete(self, *args, **kwargs):
self.document.delete()
return super().delete(*args, **kwargs)
forms.py
class CategoryForm(forms.ModelForm):
class Meta:
model = Category
fields = ['name', 'est_pr_sqft', 'est_duration', 'preceding_job', 'category_notes']
class CategoryFullForm(CategoryForm):
files = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}),required=False)
class Meta(CategoryForm.Meta):
fields = CategoryForm.Meta.fields + ['files']
views.py
####### CATEGORY VIEWS ########
class CategoryListView(LoginRequiredMixin, ListView):
model = Category
template_name = 'ProjectManagementApp/PM-Category-List.html'
context_object_name = 'categories'
slug_field = 'project_slug'
success_url = reverse_lazy('Category-list')
class CategoryDetailView(LoginRequiredMixin, DetailView):
model = Category
template_name = 'ProjectManagementApp/PM-Category-Detail.html'
slug_field = 'category_slug'
def get_context_data(self, **kwargs):
context = super(CategoryDetailView, self).get_context_data(**kwargs)
context['files'] = CategoryFiles.objects.all()
#context['photos'] = CategoryPhotos.objects.all()
return context
class CategoryCreateView(LoginRequiredMixin, CreateView):
model = Category
form_class = CategoryFullForm
template_name = 'ProjectManagementApp/PM-Category-Create.html' # Replace with your template.
#success_url = reverse_lazy('category-detail')
slug_field = 'category_slug'
def post(self, request, *args, **kwargs):
form_class = self.get_form_class()
form = self.get_form(form_class)
files = request.FILES.getlist('files')
if form.is_valid():
author = request.user
name = form.cleaned_data['name']
est_pr_sqft = form.cleaned_data['est_pr_sqft']
est_duration = form.cleaned_data['est_duration']
preceding_job = form.cleaned_data['preceding_job']
category_notes = form.cleaned_data['category_notes']
category_obj = Category.objects.create(name=name,est_pr_sqft=est_pr_sqft,est_duration=est_duration,preceding_job=preceding_job,category_notes=category_notes,author=author)
for f in files:
CategoryFiles.objects.create(category_id=category_obj,document=f)
return HttpResponseRedirect(reverse_lazy('Category-list'))
else:
return self.form_invalid(form)
class CategoryUpdateView(LoginRequiredMixin, UpdateView): #UserPassesTestMixin - makes sure user who made entry is only one who can update it.
model = Category
form_class = CategoryFullForm
template_name = 'ProjectManagementApp/PM-Category-Create.html' # Replace with your template.
slug_field = 'category_slug'
success_url = reverse_lazy('Category-list')
def post(self, request, *args, **kwargs):
form_class = self.get_form_class()
form = self.get_form(form_class)
files = request.FILES.getlist('files')
if form.is_valid():
author = request.user
name = form.cleaned_data['name']
est_pr_sqft = form.cleaned_data['est_pr_sqft']
est_duration = form.cleaned_data['est_duration']
preceding_job = form.cleaned_data['preceding_job']
category_notes = form.cleaned_data['category_notes']
category_obj = Category.objects.create(name=name,est_pr_sqft=est_pr_sqft,est_duration=est_duration,preceding_job=preceding_job,category_notes=category_notes,author=author)
for f in files:
CategoryFiles.objects.create(category_id=category_obj,document=f)
return HttpResponseRedirect(reverse_lazy('Category-list'))
else:
return self.form_invalid(form)
#
# #Doesnt allow you to update other users post
# #def test_func(self):
# # project = self.get_object()
# # if self.request.user == post.author:
# # return True
# # return False
#
#
def form_valid(self,form):
form.instance.author = self.request.user
return super().form_valid(form)
class CategoryDeleteView(LoginRequiredMixin, DeleteView): #UserPassesTestMixin - makes sure user who made entry is only one who can update it.
model = Category
template_name = 'ProjectManagementApp/PM-Category-Delete.html'
slug_field = 'category_slug'
success_url = reverse_lazy('Category-list')
#Doesnt allow you to delete other users post
#def test_func(self):
# project = self.get_object()
# if self.request.user == post.author:
# return True
# return False
If the urls.py/admin.py are needed am happy to provide, but don't think they are needed, as well as any of the html files.
I have trouble getting the current instance's fields on my UpdateView. How do I get the specific instance based on its id?
views.py
class ShowUpdate(UpdateView):
model = Show
fields = ['description', 'season', 'episode']
def post(self, request, **kwargs):
request.POST = request.POST.copy()
request.POST['description'] = "how to get instance description?" # problem here
request.POST['season'] = 2
return super(ShowUpdate, self).post(request, **kwargs)
models.py
class Show(models.Model):
owner = models.ForeignKey(User, null=True, default=True, related_name='o')
title = models.CharField(max_length=100)
description = models.TextField(default='N/A', blank=True, max_length=250)
season = models.IntegerField(default=0)
episode = models.IntegerField(default=0)
def get_absolute_url(self):
return reverse('show:index')
def __str__(self):
return self.title
Look to the UpdateView docs
This View has method get_object(self, queryset=None)
In you case just need to call it in POST method something like this:
class ShowUpdate(UpdateView):
model = Show
fields = ['description', 'season', 'episode']
def post(self, request, **kwargs):
self.object = self.get_object()
request.POST = request.POST.copy()
request.POST['description'] = self.object.description
request.POST['season'] = 2
return super(ShowUpdate, self).post(request, **kwargs)
I am working on creating a form that can save data to one of four tables based on the model the user picks from a different view. I don't want to create the same form for each model though.
Is there a way to pass the model name to the form when the user clicks submit?
Here is the code:
models.py
class TagModel(MP_Node):
slug = models.SlugField(max_length=64, blank=True)
name = models.CharField(max_length=64)
generic_objecttag_set = GenericRelation('ObjectTag')
def __str__(self):
return self.name
class Meta:
unique_together = (
('slug',),
)
abstract = True
class Concept(TagModel):
class Meta:
verbose_name = 'Concepts'
class Difficulty(TagModel):
class Meta:
verbose_name = 'Difficulty'
class QuestionType(TagModel):
class Meta:
verbose_name = 'Question Type'
class QuestionFormat(TagModel):
class Meta:
verbose_name = 'Question Format'
forms.py
class TagModelForm(forms.ModelForm):
def clean(self):
cleaned_data = super(TagModelForm, self).clean()
cleaned_data['slug'] = slugify(cleaned_data.get('name', ''))
return cleaned_data
class Meta:
model = models.TagModelForm
fields = ('slug', 'name',)
widgets = {
'slug': forms.HiddenInput(),
}
views.py
class TagCreateView(FormView):
form_class = forms.TagModelForm
template_name = 'tags/create.html'
#method_decorator(permission_required('tags.add_tag'))
def dispatch(self, request, *args, **kwargs):
arg_model = kwargs.get('tree_name', None)
if arg_model:
self.curr_model = get_model('tags', arg_model)
return super(TagCreateView, self).dispatch(request, *args, **kwargs)
def form_valid(self, form):
data = form.cleaned_data
curr_model = self.curr_model
curr_model.add_root(**data)
return super(TagCreateView, self).form_valid(form)
def get_success_url(self):
return reverse('tags:index')
I would definitely try form inheritance and do something like:
class TagForm(forms.ModelForm):
def clean():
#...
# whatever other methods here, etc.
class ConceptTagForm(TagForm):
class Meta:
model = models.Concept
class DifficultyTagForm(TagForm):
class Meta:
model = models.Difficulty
# etc