Why django model save function does not respond? - python

I am trying to create a blog post model and I added a schedule filed on Django model that I can schedule my post by date and time if schedule time == now. Then post should be verified and display to dashboard so for this I used def save function. But save function does not respond. When I tried to schedule a blog post from admin panel it did not change verified = True. Here is code what I did so far:
from django.utils import timezone
now = timezone.now() # get the current time
class Blog(models.Model):
author = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="post")
title = models.CharField(_("Title of blog post"),
max_length=250, null=True, blank=True)
header = models.CharField(
_("Blog title eg. TIPS, "), max_length=250, null=True, blank=True)
slug = models.SlugField(_("Slug of the title"), max_length=250,
unique_for_date='publish', null=True, blank=True)
photo = models.ImageField(_("Blog post main image"), default="img.png",
null=True, blank=True, upload_to='users/avatar')
read_time = models.TimeField(
_("Blog post read time"), null=True, blank=True)
category = models.ForeignKey(Category, verbose_name=_(
"Blog category list"), on_delete=models.CASCADE, null=True, blank=True)
publish = models.DateField()
tags = TaggableManager(blank=True)
description = HTMLField()
views = models.IntegerField(default="0") # <- here
verified = models.BooleanField(
_("Approved post before push on production"), default=False)
schedule = models.DateTimeField(
_("Schedule post by date and time"), auto_now=False, auto_now_add=False, null=True, blank=True)
class Meta:
verbose_name = _('blog')
verbose_name_plural = _('blogs')
def __str__(self):
return self.title
def save(self, *args, **kwargs):
if self.schedule >= now:
self.verified = True
print(self.verified)
else:
self.slug = slugify(self.title) # this also not respond
super(Blog, self).save(*args, **kwargs)

what is now ? I don't see it defined. I think that the correct way to do it is
from django.utils.timezone import now
if self.schedule <= now():
do it

The save() function is only called when you save an object. This thus means that although an object has a self.schedule that is already passed the current timestamp, one should wait until the object is saved again (and that can take a long time).
It is better to annotate the queryset with a field that specifies that it is verified when self.scheduled is less than (or equal to) Now(). We thus can define a manager that injects the annotation, and remove the verified field:
from django.db.models import BooleanField, ExpressionWrapper, Q
from django.db.models.functions import Now
class BlogManager(models.Manager):
def get_queryset(self, *args, **kwargs):
return super().get_queryset(*args, **kwargs).annotate(
verified=ExpressionWrapper(Q(scheduled__lte=Now()), BooleanField())
)
class Blog(models.Model):
author = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="post")
title = models.CharField(_("Title of blog post"),
max_length=250, null=True, blank=True)
header = models.CharField(
_("Blog title eg. TIPS, "), max_length=250, null=True, blank=True)
slug = models.SlugField(_("Slug of the title"), max_length=250,
unique_for_date='publish', null=True, blank=True)
photo = models.ImageField(_("Blog post main image"), default="img.png",
null=True, blank=True, upload_to='users/avatar')
read_time = models.TimeField(
_("Blog post read time"), null=True, blank=True)
category = models.ForeignKey(Category, verbose_name=_(
"Blog category list"), on_delete=models.CASCADE, null=True, blank=True)
publish = models.DateField()
tags = TaggableManager(blank=True)
description = HTMLField()
views = models.IntegerField(default=0)
schedule = models.DateTimeField(
_("Schedule post by date and time"), auto_now=False, auto_now_add=False, null=True, blank=True)
objects = BlogManager()

Related

Cannot assign "'1'": "Groups.profile" must be a "Profile" instance

I have Profile Model that have instance model user.. I am trying to create group using form. that group model have Profile model as instance, so how do I select authenticated user automatic to create group, I getting confused...
This is my Group Model
class Groups(models.Model):
profile = models.ForeignKey(Profile, related_name='my_groups', on_delete=models.CASCADE)
groups_name = models.CharField(max_length=150)
slug = models.SlugField(max_length=150, unique=True)
cover_pic = models.ImageField(upload_to='images/groups/', null=True, blank=True)
type_group = models.CharField(max_length=150)
created_date = models.DateTimeField(auto_now_add=True)
about_group = models.TextField(max_length=600)
members = models.ManyToManyField(Profile,through="GroupMember")
def __str__(self):
return self.groups_name
This is my profile Model
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
slug = models.SlugField(max_length=100, unique=True)
profile_pic = models.ImageField(upload_to='images/user/profile/', null=True, blank=True)
cover_pic = models.ImageField(upload_to='images/user/profile/', null=True, blank=True)
user_bio = models.TextField(null=True,blank=True, max_length=255)
designation = models.CharField(blank=True,null=True, max_length=255)
education = models.CharField(blank=True, null=True, max_length=255)
marital_status = models.CharField(blank=True, null=True, max_length=60)
hobbies = models.CharField(blank=True, null=True, max_length=500)
location = models.CharField(blank=True, null=True, max_length=500)
mobile = models.IntegerField(blank=True, null=True)
def __str__(self):
return str(self.user)
This is form for create group
class GroupCreateForm(forms.ModelForm):
class Meta:
model = Groups
fields = ('cover_pic', 'profile', 'groups_name', 'type_group', 'about_group')
profile = forms.CharField(widget=forms.TextInput(attrs={
'class': 'form-control input-group-text',
'value':'',
'id':'somesh',
'type': 'hidden',
}))
This is create group html file
this is html page
this is error..
You have set a CharField for profile in your form. When you send data to this form, it tries to make a Group record with a FK to a CharField for example "1" and this gives you error because you should pass Profile object to Group.
Depends on what exactly you want, there are some options.
You can use ModelChoiceField. Read about it in https://docs.djangoproject.com/en/3.2/ref/forms/fields/#django.forms.ModelChoiceField
Or you can use Inline FormSet and read about it in https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#inline-formsets
And an example for Inline FormSet in Creating a model and related models with Inline formsets

User object has no attribute customer

I am trying to create cart using django but i am getting this error. while I try to check that the user is authenticated or no i used customer = request.user.customer but it says user has no attribute customer
Here is my views.py
def cart(request):
if request.user.is_authenticated:
customer = request.user.customer
order, created = OrderModel.objects.get_or_create(customer=customer, complete=False)
items = order.orderitem_set.all()
else:
items = []
context = {}
return render(request, 'Home/cart.html', context)
here is my models.py
class CustomerModel(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE, null=True, blank=True, default='')
customer_name = models.CharField(max_length=1000, null=True)
customer_phone = models.CharField(max_length=20, null=True)
def __str__(self):
return self.customer_name
class OrderModel(models.Model):
customer = models.ForeignKey(CustomerModel, on_delete=models.SET_NULL, null=True, blank=True)
order_date = models.DateTimeField(auto_now_add=True)
complete = models.BooleanField(default=False,null=True,blank=True)
transaction_id = models.CharField(max_length=1000, null=True)
def __str__(self):
return str(self.id)
class OrderItem(models.Model):
product = models.ForeignKey(ProductModel, on_delete=models.SET_NULL, null=True, blank=True)
order = models.ForeignKey(OrderModel, on_delete=models.SET_NULL, null=True, blank=True)
quantity = models.IntegerField(default=0, null=True, blank=True)
date_added = models.DateTimeField(auto_now_add=True)
class Address(models.Model):
customer = models.ForeignKey(CustomerModel, on_delete=models.SET_NULL, null=True, blank=True)
order = models.ForeignKey(OrderModel, on_delete=models.SET_NULL, null=True, blank=True)
address = models.CharField(max_length=10000)
city = models.CharField(max_length=1000)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.address
I am stuck here and cant understand what to do.
I think changing the line customer = request.user.customer to customer = request.user.customermodel may solve your problem. If you want to use customer = request.user.customer add related name to your CustomerModel's field:
user = models.OneToOneField(User, on_delete = models.CASCADE, null=True, blank=True, default='', related_name='customer')
Note: Make sure that your user object has a related profile.
For example add an extra condition to your codes like following:
if hasattr(request.user, 'customer'): # If you have related name otherwise use customermodel
customer = request.user.customer
else:
# Return a proper message here
Because if your user object has no related profile this line of code will raise RelatedObjectDoesNotExist error type.
For the user field of the CustomerModel, you must set "related_name" and "related_query_name" to "customer":
user = models.OneToOneField(User, on_delete = models.CASCADE, null=True, blank=True, default='', related_name='customer', related_query_name='customer')
You have to set the "related_name" parameter in your CustomerModel customer field for reverse access
user = models.OneToOneField(User, related_name="user", on_delete = models.CASCADE, null=True, blank=True, default='')
if you don't set the related name django will generate field name + "_set" for the access (user_set in your example)

Restrict form field choices based on previous model choice in Django

I am currently attempting to create a DnD 5e Character creator using Django and SRD materials provided by WoTC. This is the first time I have ever used Django, and I am learning it as I go. I have come up against a bit of a challenge that has stone-walled me for a few days now. I have researched the issue, and after applying multiple techniques I thought may help, I've had limited luck. My question is this:
I have a number of models representing Heroes, Races, Subraces, Classes, Backgrounds and so forth. I wish to be able to restrict a users ability to choose a Subrace, based on their selection of a race beforehand.
So far I have this:
models.py
class Race(models.Model):
race_name = models.CharField(max_length=200)
race_size = models.CharField(
max_length=2, choices=SIZE_CHOICE, default='M')
race_speed = models.IntegerField(
default=30)
race_lang = models.CharField(max_length=200, null=True, blank=True)
race_str = models.IntegerField(default=0, null=True, blank=True)
race_dex = models.IntegerField(default=0, null=True, blank=True)
race_con = models.IntegerField(default=0, null=True, blank=True)
race_int = models.IntegerField(default=0, null=True, blank=True)
race_wis = models.IntegerField(default=0, null=True, blank=True)
race_cha = models.IntegerField(default=0, null=True, blank=True)
skill_spend = models.IntegerField(default=0, null=True, blank=True)
race_extra = models.TextField(max_length=2000, blank=True, null=True)
race_source = models.CharField(max_length=200, blank=True)
def __str__(self):
return self.race_name
class Meta:
verbose_name = 'Race'
verbose_name_plural = 'Races'
class Subrace(models.Model):
sub_name = models.CharField(max_length=200)
sub_size = models.CharField(
max_length=2, choices=SIZE_CHOICE, default='M', null=True)
sub_speed = models.IntegerField(
default=30, null=True)
sub_lang = models.CharField(max_length=200, null=True, blank=True)
sub_str = models.IntegerField(default=0, null=True, blank=True)
sub_dex = models.IntegerField(default=0, null=True, blank=True)
sub_con = models.IntegerField(default=0, null=True, blank=True)
sub_int = models.IntegerField(default=0, null=True, blank=True)
sub_wis = models.IntegerField(default=0, null=True, blank=True)
sub_cha = models.IntegerField(default=0, null=True, blank=True)
sub_extra = models.TextField(max_length=2000, null=True, blank=True)
sub_parent = models.ForeignKey(Race, on_delete=models.CASCADE, null=True)
def __str__(self):
return self.sub_name
class Meta:
verbose_name = 'Subrace'
verbose_name_plural = 'Subraces'
class Hero(models.Model):
def roll_stats():
d6 = die.Dice(6)
list_stats = d6.roll(4)
list_stats.sort()
add = sum(list_stats[1:4])
return add
hero_name = models.CharField(max_length=200)
author = models.ForeignKey(User, null=True)
hero_subrace = models.ForeignKey(
Subrace, on_delete=models.CASCADE, null=True, blank=True)
pub_date = models.DateTimeField('date published', blank=True, null=True)
hero_klass = models.ForeignKey(Klass, on_delete=models.CASCADE, null=True)
hero_race = models.ForeignKey(Race, on_delete=models.CASCADE)
background = models.ForeignKey(
Background, on_delete=models.CASCADE, null=True)
health = models.IntegerField(blank=True, null=True)
hero_exp = models.IntegerField(default=0, null=True)
hero_alignment = models.ForeignKey(Alignment, blank=True, null=True)
hero_str = models.IntegerField(default=roll_stats, null=True, blank=True)
hero_dex = models.IntegerField(default=roll_stats, null=True, blank=True)
hero_con = models.IntegerField(default=roll_stats, null=True, blank=True)
hero_int = models.IntegerField(default=roll_stats, null=True, blank=True)
hero_wis = models.IntegerField(default=roll_stats, null=True, blank=True)
hero_cha = models.IntegerField(default=roll_stats, null=True, blank=True)
def save(self, *args, **kwargs):
"Returns a hero's hp"
die_str = str(self.hero_klass.hit_dice)
die_nums = die_str.split("d")
die_val = int(die_nums[1])
die_roll = int(die_nums[0])
hp_die = die.Dice(die_val)
results = hp_die.roll(die_roll)
self.health = sum(results)
super(Hero, self).save(*args, **kwargs)
def __str__(self):
return self.hero_name
def get_absolute_url(self):
return reverse('hero.views.detail', args=[str(self.id)])
class Meta:
verbose_name = 'Hero'
verbose_name_plural = 'Heroes'
views.py
def new_hero(request):
user = request.user
if request.method == "POST":
form = HeroForm(request.POST)
if form.is_valid():
hero = form.save(commit=False)
hero.author = request.user
hero.save()
return redirect('detail', hero.pk)
else:
form = HeroForm()
return render(request, 'new_hero.html', {'form': form, 'user': user})
forms.py
class HeroForm(forms.ModelForm):
class Meta:
model = Hero
fields = ['hero_name', 'hero_race', 'hero_subrace',
'hero_klass', 'hero_exp', 'health', 'background',
'hero_str', 'hero_dex', 'hero_con', 'hero_int',
'hero_wis', 'hero_cha', 'hero_alignment']
def __init__(self, *args, **kwargs):
super(HeroForm, self).__init__(*args, **kwargs)
for fieldname in ['hero_str', 'hero_dex', 'hero_con', 'hero_int', 'hero_wis', 'hero_cha']:
self.fields[fieldname].disabled = True
race = Race.objects.all()
for name in race:
self.fields['hero_subrace'].queryset = Subrace.objects.filter(sub_parent=name)
I have trialled a few different techniques, but this is where I am now. This:
for name in race:
self.fields['hero_subrace'].queryset = Subrace.objects.filter(sub_parent=name)
is my most recent addition to my app. At the hero creation screen I am hit with a blank box of choices, as opposed to the full unrestricted list without the loop or queryset.
Basically I'm hoping that someone has some advice for me on a method I may be overlooking, or something that I've missed, or simply not found yet. Also please feel free to critique the rest of the code, like I said this is my first Django App :). Also my first Stack Overflow question, so thanks :)
For anyone that is wondering, I used django-smart-selects to solve my problem.
base.html
<script type="text/javascript" src="{% static 'smart-selects/admin/js/chainedfk.js' %}"></script>
<script type="text/javascript" src="{% static 'smart-selects/admin/js/bindfields.js' %}"></script>
I added the above html to my {% load staticfiles %} call.
and changed models.py:
models.py
from smart_selects.db_fields import ChainedForeignKey
class Hero(models.Model):
....
race = models.ForeignKey(Race, on_delete=models.CASCADE)
subrace = ChainedForeignKey(Subrace,
chained_field="race",
chained_model_field="race",
show_all=False,
auto_choose=True,
blank=True,
null=True)
Now I have a subrace field that is dynamically update when the user chooses a Race.

Django Many to Many Relationship on both models

I am building a small web application where people will be able to join shows and for it to show that they joined it on a template. However, my current problem is that on my User Profile model I have added a couple of shows but the Show model object doesn't show that the User Profile is apart of it. How can I achieve this in Django?
models.py:
from django.contrib.auth.models import User
from django.db import models
from django.db.models.signals import post_save
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, unique=True, related_name='user')
bio = models.TextField(max_length=500, blank=True)
image = models.ImageField(blank=True, upload_to="uploads/profile")
show = models.ManyToManyField('Show', blank=True)
def __str__(self):
return str(self.user)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
class Show(models.Model):
user = models.ForeignKey(User, null=True, blank=True)
name = models.CharField(max_length=120, null=True, blank=True)
description = models.TextField(max_length=500, null=True, blank=True)
image = models.ImageField(null=True, blank=True, upload_to="uploads/show")
venue = models.CharField(max_length=120, null=True, blank=True)
date = models.DateField(null=True, blank=True)
genre = models.CharField(max_length=120, null=True, blank=True)
def __str__(self):
return self.name

How can I get user selected radio option? Django

I have a model named UserAddress and a form created from the same model which is UserAddressForm.
class UserAddress(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
address = models.CharField(max_length=120)
address2 = models.CharField(max_length=120, null=True, blank=True)
city = models.CharField(max_length=120, null=True, blank=True)
phone = models.CharField(max_length=120)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now_add=False, auto_now=True)
def __unicode__(self):
return self.get_address()
def get_address(self):
return"%s,%s,%s,%s" %(self.address, self.address2,self.city,self.phone)
I am displaying all the user addresses in the html with a radio check-box. I want to get the user selected address in my view and assign to another model instance which I am unable to figure out. How can I do this?
If your models structure is following:
class UserAddress(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
address = models.CharField(max_length=120)
address2 = models.CharField(max_length=120, null=True, blank=True)
city = models.CharField(max_length=120, null=True, blank=True)
phone = models.CharField(max_length=120)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now_add=False, auto_now=True)
def __unicode__(self):
return self.get_address()
def get_address(self):
return"%s,%s,%s,%s" %(self.address, self.address2,self.city,self.phone)
class Order(models.Model):
address = models.ForeignKey(UserAddress)
You can make a form based on Order model, put ModelChoiceField and specify widget to be RadioSelect
from django import forms
class OrderForm(forms.Form):
address = forms.ModelChoiceField(
queryset=UserAddress.objects.all(),
widget=forms.widgets.RadioSelect(),
)
In that case when you handle OrderForm submit you will have address which user is choose.

Categories

Resources