It's my first time creating a Django website with models, and in my first attempt to insert data into my table I'm getting this error.
My models are as follows:
class User(AbstractUser):
pass
#https://docs.djangoproject.com/en/3.1/topics/auth/default/
class Listing(models.Model):
listingID = models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="listID")
created_by = models.ForeignKey(User, on_delete=models.SET_NULL, related_name="myListing", null=True)
watchers = models.ManyToManyField(User, blank=True, related_name="watchlist")
title = models.CharField(max_length=30)
description = models.TextField()
creation_date = models.DateField(auto_now=True)
img_url = models.URLField()
active = models.BooleanField(default=True)
def __str__(self):
return f"{self.title}"
class Bid(models.Model):
listing = models.ForeignKey(Listing, on_delete=models.SET_NULL, related_name="bidsMadeOnMe", null=True, blank=True)
user = models.ForeignKey(User, on_delete=models.SET_NULL, related_name="myBids", null=True)
price = models.FloatField()
creation_date = models.DateField(auto_now=True, null=True)
def __str__(self):
return f"Bid={self.price}"
and the view that handles the form submission is this one:
#login_required
def create_listing(request):
if request.method == "POST":
user = User.objects.get(username=request.user.username)
l = Listing(created_by=user,
title=request.POST["title"],
description=request.POST["desc"],
# https://stackoverflow.com/questions/12176585/handling-dates-over-request-get
creation_date=models.DateTimeField(auto_now_add=True),
img_url=request.POST["image_url"]
)
l.save()
b = Bid(l,
user,
request.POST["initial_bid"],
models.DateTimeField(auto_now_add=True)
)
b.save()
return render(request, "auctions/index.html")
I know the problem is the way I'm adding the data but I can't fix it. Can someone give me some light?
Your problem (well, several actually) is this:
b = Bid(l, user, request.POST["initial_bid"], models.DateTimeField(auto_now_add=True))
You're constructing a model instance by positional arguments instead of keyword arguments. This can be done, but then the invisible "id" column that has been added to the Bid model, is the first argument.
In Django we never construct models like that, but always use keyword arguments, so we're not depending on field order:
b = Bid(listing=l, user=user, ...))
Once you're solved that, your next problem is the date field.
Don't assign fields to model instances. Fields are class declarations, they don't belong on instances. Fields describe on a class (= a Model), what kind data to expect. On the instance, you assign that data.
In this case, your definition for the field is wrong on the model and on the instance you shouldn't even assign it - it will be automatically filled.
Overall, it feels like you haven't gone through Django's tutorial or did not fully understand the concepts. I suggest you go through it.
Related
Trying to create a column in my model called, stock_count, that finds the sum of the total string objects in my ArrayField(), aka stock_list. Here is my function.
def total_stocks_calc(self):
self.stock_count = Bucket.objects.aggregate(Sum('stock_list', distinct=True))
self.save()
However it doesn't seem to be doing anything, no calculating, leaving the field blank in my model, admin page, and DRF interface...
EDIT: updated post with new implementation.
Here is my model.
class Bucket(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='buckets')
users = models.ManyToManyField(settings.AUTH_USER_MODEL)
category = models.CharField(max_length=30, choices=category_options)
name = models.CharField(max_length=35)
created = models.DateTimeField(default=timezone.now)
slug = models.SlugField(unique=True, blank=True)
stock_count = models.IntegerField(blank=True, null=True)
stock_list = ArrayField(models.CharField(max_length=6,null=True),size=30,null=True)
about = models.CharField(max_length=75)
objects = models.Manager()
bucketobjects = BucketObjects()
class Meta:
ordering = ('-created',)
def total_stocks_calc(self):
self.stock_count = Bucket.objects.annotate(stock_count=F('stock_list__len'))
self.save()
def __unicode__(self):
return self.stock_list
Would like to know the proper way to count total items in ArrayField(), thank you in advance.
The ArrayField provides the len lookup field, through that you can get the count
like
from django.db.models import F
Bucket.objects.annotate(stock_count=F('stock_list__len'))
This question is in relation to project 2 of the cs50 course which can be found here
I have looked at the following documentation:
Django queryset API ref
Django making queries
Plus, I have also taken a look at the aggregate and annotate things.
I've created the table in the template file, which is pretty straight forward I think. The missing column is what I'm trying to fill. Image below
These are the models that I have created
class User(AbstractUser):
pass
class Category(models.Model):
category = models.CharField(max_length=50)
def __str__(self):
return self.category
class Listing(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
description = models.TextField()
initial_bid = models.IntegerField()
category = models.ForeignKey(Category, on_delete=models.CASCADE)
date_created = models.DateField(auto_now=True)
def __str__(self):
return self.title
class Bid(models.Model):
whoDidBid = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
list_item = models.ForeignKey(Listing, default=0, on_delete=models.CASCADE)
bid = models.IntegerField()
category = models.ForeignKey(Category, on_delete=models.CASCADE)
date = models.DateTimeField(auto_now=True)
def __str__(self):
return_string = '{0.whoDidBid} {0.list_item} {0.bid}'
return return_string.format(self)
This is the closest I could come to after a very long time. But the result I get is just the number 2. Ref image below
Listing.objects.filter(title='Cabinet').aggregate(Max('bid'))
Where 'Cabinet' is a Listing object that I have created. And placed two bids on them.
So the question is, how do I get the Maximum bid value(i.e. 110 for this case) for a particular listing? Using the orm. I think if I used a raw sql query, I could build a dict, send it to the template with the queryset. Then while looping through the queryset, get the value for the key, where the key is the name of the listing or something along those lines. Nah, I would like to know how to do this through the ORM please.
Here's answer #1
Bid.objects.filter(list_item__title='Cabinet').prefetch_related('list_item').aggregate(Max('bid'))
What happens when you try this (sorry, I don't have any objects like this to test on):
Bid.objects.values(list_item__title).prefetch_related('list_item').annotate(Max('bid'))
I have the following model setup:
class Model1(models.Model):
val1_1 = models.CharField(max_length=25, blank=True)
val1_2 = models.CharField(max_length=25, blank=True)
user = models.ForeignKey('users.User', on_delete=models.PROTECT, related_name='model1')
class Model2(models.Model):
val2_1 = models.BinaryField()
model1_link = models.ForeignKey(Case, on_delete=models.CASCADE, related_name='model2')
class Model3(models.Model):
id = models.BigAutoField(primary_key=True)
model2_link = models.ForeignKey(Model2, on_delete=models.CASCADE, related_name='model3')
val3_1 = models.CharField(max_length=50)
class Model4(models.Model):
id = models.BigAutoField(primary_key=True)
model3_link = models.ForeignKey(Model3, on_delete=models.CASCADE, related_name='model4', null=True, default=None)
pred = models.CharField(max_length=50)
# These fields are NOT FILLED IN during creation of an instance, and are instead updated later on with a separate query
disputed_on = models.DateTimeField(blank=True, null=True)
suggested_by = models.ForeignKey('users.User', on_delete=models.PROTECT, related_name='submitted_disputes', blank=True, null=True)
At times, I will want to access Model4's specific instance, to actually fill in a value in fields disputed_on & suggested_by, by traversing all the way from Model1. I do that currently as such:
query = Model1.objects.filter(id=some_chosen_id).get().model2.last().model3.filter(val3_1=some_chosen_value).get().model4.last()
The output of that query is a single model instance, not a QuerySet.
Next, I calculate new values I want to insert:
dispute_date = datetime.now(tz.tzutc())
if request.user.is_authenticated:
disputer = request.user
else:
# Assume admin (first entry)
disputer = User.objects.get(pk=1)
And I save new values by doing the following:
query.disputed_on = dispute_date
query.suggested_by = disputer
query.save()
Now, the strangest thing happens - my postgres DB gives me an error stating, the following:
postgres_1 | 2020-03-30 11:45:31.700 AEDT [4169] ERROR: duplicate key value violates unique constraint "users_user_username_key"
Now, the way I read it, calling prediction.save() also results in DB trying to update table of users. But I do not call for that anywhere in the code!
Any ideas why is that happening?
That problem seems to be gone when I modify my query to stay as a QuerySet, and use .update() method instead...
I have two Models in my application in Django
The Change model is only for storing the change logs made in Model Ip
My models.py
class Change(models.Model):
author = models.ForeignKey('auth.User', null=False, on_delete=models.CASCADE, default='auth.User')
ip = models.ForeignKey('Ip', on_delete=models.CASCADE, default='')
old_cluster = models.ForeignKey('Cluster', on_delete=models.CASCADE, default='')
old_status = models.ForeignKey('Status', on_delete=models.CASCADE, default='')
new_cluster = models.CharField(max_length=20)
new_status =models.CharField(max_length=20)
change_date = models.DateTimeField(default=timezone.now)
class Ip(models.Model):
author = models.ForeignKey('auth.User', null=False, on_delete=models.CASCADE, default='auth.User')
number = models.CharField(max_length=20, unique=True, default='')
status = models.ForeignKey('Status', on_delete=models.CASCADE, default='')
cluster = models.ForeignKey('Cluster', on_delete=models.CASCADE, default='')
created_date = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.number
class Meta:
ordering = ('number',)
my views.py
def ip_edit(request, id):
ip_edit = get_object_or_404(Ip, id=id)
form = EditManagementForm(request.POST, instance=ip_edit)
change_form = ChangeLogsForm()
if request.method == "POST":
if form.is_valid():
ip_edit = form.save(commit=False)
ip_edit.save()
change_form = ChangeLogsForm(request.POST)
if change_form.is_valid():
ip_change = change_form.save(commit=False)
ip_change.author = request.user
ip_change.ip = request.number
ip_change.save()
return redirect('/app/management')
else:
form = EditManagementForm(instance=ip_edit)
args = {
'form': form,
}
return render(request, 'app/ip_edit.html', args
and my forms.py
class EditManagementForm(forms.ModelForm):
class Meta:
model = Ip
fields = (
'number',
'status',
'cluster',
)
widgets = {
'number': TextInput(attrs={'class': 'ls-form-text'}),
}
class ChangeLogsForm(forms.ModelForm):
class Meta:
model = Change
fields = (
'ip',
'old_cluster',
'old_status',
'new_cluster',
'new_status',
)
when I save the ip information editing, no error occurs, but it also does not save the Model Change information
could you help me and let me know if there is any more correct and simple way to store a history of changes in a Model?
Since your Change model has a foreign key relation to Ip model and since ip_change in your view.py presents the instance of Change model then you should replace ip_change.ip = request.number with ip_change.ip = ip_edit because ip_edit is the instance of Ip model.
Do you want to perform the save operation on Ip and Change models only when both forms are valid? If you want that then this code has one really serious problem which people sometimes overlook and that problem is related to violation of database integrity. Just try to think about the situation when form.is_valid() returns True and change_form.is_valid() returns False. If that happens you will only save the data into Ip database table and nothing into Change database table because this line ip_change.save() will not be reached. If that happens the data integrity will be ruined and I guess you don't want that - you probably want to ensure that both saveoperations either executes or not. You should validate both forms at the same time like if form.is_valid() and change_form.is_valid() and put the rest of logic into that block.
P.S.
Since I started to talk about the violation of database integrity you should also have a look at atomic database transactions, it can be useful to know.
I am seeking an advice on how to approach the following problem:
I am having these models: Event > EventAttendees > EventRoster.
Every event has attendees (users) which I would like to assign to specific positions (attributes of EventRoster) for that particular Event.
Example: -Event(Football/Soccer game), attendees: (Bob, John, Mike, Steve), EventRoster: (Bob = goaltender, John = left wing, Mike = center, Steve = defence)
Idea is to have a form for event, where anyone from attendees can be assigned to any of the positions. Each form field would represent a position, where attendee can be selected, if that attendee was not already selected for different position.
My problem is, that I am selecting attendees from EventAttendees.objects.all() or .filter(event__pk=pk) without updating this queryset to exclude attendees that are already selected for some other position.
What I am aiming for is to exclude attendee from queryset if that attendee is already selected in form field (position). Basically to have empty queryset once all attendees are assigned to all positions.
What would be the best way to approach this? I have found similarities in so called chained fields, but I guess these are not applicable in this scenario. Probably I will not be able to this without ajax as field values on form will not change unless form is submitted.
Thank you in advance for your support!
class Event(models.Model):
name = models.CharField(max_length=30, blank=True, null=True)
attendees = models.ManyToManyField(User, through='EventAttendees')
class EventAttendees(models.Model):
user = models.ForeignKey(User, related_name='user_event')
event = models.ForeignKey(Event, related_name='ice')
def __str__(self):
return self.user.username
class Meta:
unique_together = ('user','event')
class EventRoster(models.Model):
event = models.ForeignKey(Event, related_name='event_roster')
goalie = models.CharField(max_length=20, blank=True, null=True, unique=True)
center = models.CharField(max_length=20, blank=True, null=True, unique=True)
left_wing = models.CharField(max_length=20, blank=True, null=True, unique=True)
defensemen = models.CharField(max_length=20, blank=True, null=True, unique=True)
class RosterForm(forms.ModelForm):
goalie = forms.ModelChoiceField(queryset=EventAttendees.objects.none())
center = forms.ModelChoiceField(queryset=EventAttendees.objects.none())
left_wing = forms.ModelChoiceField(queryset=EventAttendees.objects.none())
defensemen = forms.ModelChoiceField(queryset=EventAttendees.objects.none())
def __init__(self, *args, **kwargs):
super(RosterForm, self).__init__(*args, **kwargs)
self.fields['goalie'].queryset = EventAttendees.objects.filter(event__pk=50).distinct()
self.fields['center'].queryset = EventAttendees.objects.filter(event__pk=50).distinct()
self.fields['left_wing'].queryset = EventAttendees.objects.filter(event__pk=50).distinct()
self.fields['defensemen'].queryset = EventAttendees.objects.filter(event__pk=50).distinct()
class Meta:
model = EventRoster
fields = ['goalie','center','left_wing','defensemen']
I cannot really undestand the logic except i see the whole code i.e views and forms but i think the exclude() function would come in handy when querying the model