using django 2.0.2 python3.4
skip details models.py
class Post(models.Model):
postuid = models.BigAutoField(
db_column='postUID', primary_key=True)
useruid = models.Foreignkey .... skip
content = models.Text ....
registerdate = models.Date ....
class KeepPost(models.Model):
keeppostuid = models.BigAutoField(
db_column='KeepPostUID', primary_key=True)
useruid = models.ForeignKey(
'Userinfo', db_column='UserUID', on_delete=models.CASCADE)
postuid = models.ForeignKey(
'Post', db_column='PostUID', on_delete=models.DO_NOTHING)
content = models.TextField(db_column='Content')
registerdate = models.DateTimeField(
db_column='RegisterDate')
keepdate = models.DateTimeField(
db_column='KeepDate')
class ReportPost(models.Model):
reportuid=models.BigAutoField(
db_column='ReportUID', primary_key=True)
postuid=models.ForeignKey(
'Post', db_column='PostUID', on_delete=models.DO_NOTHING)
#useruid is reporter
useruid=models.ForeignKey(
'Userinfo', db_column='UserUID', on_delete=models.CASCADE)
registerdate = models.DateTimeField(
db_column='RegisterDate'
Post to KeepPost
Post.objects.get(postuid=1) or Post.objects.filter(useruid=1)
KeepPost.objects.create(modelobjects or queryset)
get() is return model object , filter() is return queryset
if i want delete after reported
why use on_delete DO_NOTHING -> I want to keep a record even if ReportedPost is deleted
just one post deleted
ex)
postmodel = Post.objects.get(postuid=request.get("postuid"))
want that models move to KeepPost and delete
postmodel.delete()
if user want delete account
usermodel = User.objects.get(useruid=useruid)
Postquery = usermodel.post_set.all()
reportPost = ReportPost.objects.filter(Q(postuid__in=Postquery))
i think move to KeepPost after intersect Postquery and reportPost
usermodel.delete()
Here are what i might simply do.
1. Remove KeepPost model.
2. Change Post model
class Post(models.Model):
user = models.ForeignKey(User, related_name='posts', on_delete=models.CASCADE)
content = models.TextField()
registerdate = models.DateTimeField(auto_now_add=True)
is_archived = models.BooleanField(default=False)
archived_date = models.DateTimeField()
#property
def archive_post(self):
if not self.is_archived:
self.is_archived = True
self.archived_date = datetime.now()
self.save()
Whats happening here??
First you don't need a KeepPost model it is redundant since deleting and keeping a Post object will still maintain the data.
Removed postuid = models.BigAutoField(db_column='postUID', primary_key=True). Django will automatically assign a primary key id.
Add is_archived and archived_date the simpliest way to keep an instance is not to delete it at all.
Now in your view you can simple use this, either you get your source from single instance or queryset.
post = Post.objects.get(pk=1) # or id=1
post.archive_post
OR
posts = Post.objects.filter(user_id=1)
for post in posts:
post.archive_post
If you want to delete a Post instance forever then call .delete() method.
Related
I have two models, ChatBox and Message. I want to loop through all chats and display them, and I want to display a count of unseen messages (Message model is in a foreign key relation) for each chat.
Could anyone please help me to do this since I ve been strugling with it for few hours.
Firstly I wanted to pass each object from the loop to django filters/tags and add a count of unseen messages to it, but I got advised to use objects.annotation. However, i can not find ways to implement none of these.
Here is my view that displays inbox:
class InboxView(LoginRequiredMixin, ListView):
model = ChatBox
template_name = 'chat/inbox.html'
def get_queryset(self):
# getting all chats for a request.user
object_list = ChatBox.objects.filter(Q(user1=self.request.user) \
| Q(user2=self.request.user)).all()
return object_list
And here are my models:
class ChatBox(models.Model):
user1 = models.ForeignKey(CustomUser,
on_delete=models.CASCADE, related_name='user1')
user2 = models.ForeignKey(CustomUser,
on_delete=models.CASCADE, related_name='user2')
slug = models.SlugField(_("Slug"), max_length=255, unique=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Message(models.Model):
chat = models.ForeignKey(ChatBox, on_delete=models.CASCADE)
sender = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='sender')
body = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
seen = models.BooleanField(default=False)
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.
I have two models as Author and Comment
One is Comment and it has a ForeinKey points to Author(BlogUser)
class Comment(models.Model):
body = models.TextField('body', max_length=500)
created_time = models.DateTimeField('create_time', default=now)
last_mod_time = models.DateTimeField('last_mod_time', default=now)
author = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='author', on_delete=models.CASCADE)
article = models.ForeignKey(Article, verbose_name='article', on_delete=models.CASCADE)
parent_comment = models.ForeignKey('self', verbose_name="parent_comment", blank=True, null=True, on_delete=models.CASCADE)
is_approved = models.BooleanField('is_approved', default=True, blank=False, null=False)
is_enabled = models.BooleanField('is_enabled', default=True, blank=False, null=False)
is_deleted = models.BooleanField('is_deleted', default=True, blank=False, null=False)
Author Model
class BlogUser(AbstractUser):
qq_number = models.CharField('QQ', max_length=20, default='')
I am trying to get all the comments related to a specified Article and display the comments list by the format of usernames and comment bodys.
In the view I filter all the comments by the article id, but after serializing the filter queryset, it gives me only the Author's primary id, how could I get the other feilds of Author? Shall I write a function by myself or there is some easier way to do it?
The view:
def get_comment_list(request, article_id):
if request.GET:
comment_list = models.Comment.objects.filter(article_id = article_id)
data = serializers.serialize('json',comment_list)
return HttpResponse(data, content_type="application/json")
else:
PermissionDenied('Not accept post')
You need to iterate the comment_list and with the member operator to access the fields of author
eg: comment_list[0].author.field_name
NOTE: Field name could be any field name that has been decleared in AUTH_USER_MODEL table like first_name, last_name or username.
By default, django serializer does not provide information from ForeignKey. I would also recommend using Django Rest Framework Serializer(Denial Roseman mentioned in the comments) if you have the scope of using it.
Still you can use the django serializer, but you will need to override the json.Serializer's end_object() method. There you canget the values of the user object like following example:
from django.core.serializers.json import Serializer
class CustomSerializer(Serializer):
def end_object(self, obj):
for field in self.selected_fields:
if field in self._current.keys():
continue
else:
try:
self._current[field] = getattr(obj.author, field) # Fetching the data from ForeignKey
except AttributeError:
pass
super(CustomSerializer, self).end_object(obj)
# usage
data = CustomSerializer().serialize(
Comment.objects.all(),
fields = (
'pk',
# other fields in Comment Object
'username' # it belongs to Author Model
)
Downside of this solution is that, if BlogUser has same field as Comment, then it will fetch the value of Comment.
More Advanced Implementation:
class CustomSerializer(Serializer):
def end_object(self, obj):
for field in self.selected_fields:
if field in self._current.keys():
continue
else:
if field.find('__') > -1:
try:
fks = field.split('__')
curr_value = obj
while(len(fks)>0):
current_key = fks.pop(0)
curr_value = getattr(curr_value, current_key)
self._current[field] = curr_value
except AttributeError:
pass
super(CustomSerializer, self).end_object(obj)
# usage
data = CustomSerializer().serialize(
Comment.objects.all(),
fields = (
'pk',
# other fields in Comment Object
'author__username' # it belongs to Author Model
)
Here i have mentioned my model,serializer and view. Actually im new to this concepts. I don't how to get the last added product.
Models.py
class Products(models.Model):
name = models.CharField(max_length=100)
image = models.CharField(max_length=100, null=True)
categories = models.ArrayModelField(
model_container=Category,
model_form_class=CategoryForm
)
specifications = models.ArrayModelField(
model_container=Specifications,
model_form_class=SpecificationsForm
)
description = models.CharField(max_length=1000)
reviews = models.ArrayModelField(
model_container=Reviews,
model_form_class=ReviewsForm
)
drizzly = models.BooleanField(default=False)
complete = models.BooleanField(default=False)
comment = models.CharField(max_length=500)
click_count = models.IntegerField()
serializer.py
class ProductsSerializer(serializers.ModelSerializer):
class Meta:
model = Products
fields = ('id',
'name',
'image',
'categories',
'specifications',
'description',
'reviews',
'drizzly',
'complete',
'comment',
'click_count')
views.py
class ProductsViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows groups to be viewed or edited.
"""
queryset = Products.objects.all()
serializer_class = ProductsSerializer
Please tell me how to do that?.
Since the last product have the highest id then you can try like this
last_product = Products.objects.order_by('-id')[0]
What I'm doing here is ordered all the project in reverse order by id then get first element from that.
The easiest way to get last product would be:
Products.objects.last()
With reverse(), you can do : Products.objects.all().reverse()[0]
For first one: Products.objects.first()
Is that what you want?
You need some "last_modified" timestamp field on your model obviously - else you have no way to know when a record has been updated:
import time
class Products(models.Model):
# your existing fields here
last_updated = models.FloatField(
"last_updated",
editable=False,
default=time.time
)
def save(self, *args, **kw):
self.last_updated = time.time()
if "update_fields" in kw:
kw["update_fields"].append("last_updated")
super(Product, self).save(*args, **kw)
and of course generate and pass the migration.
Then you can get the last updated record using QuerySet.latest(*fields):
last_updated_product = Product.objects.latest("last_modified")
I'm not using DRF so I can't tell how to plug this into your ProductsViewSet but there's certainly some documentation available...
Try
from {app_name} import Products
Products.objects.reverse()[0]
Since there is a primary key pk as default in each model created, you can filter specifically using
Products.objects.filter(order_by='pk')
Working with filtering objects by when they are added to the database using a data time field to track the updated time will provide a less error prune way to get the latest objects.
See Also:
Retrieving the latest object, Ordering model objects
models.py
class Products(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
name = models.CharField(max_length=100)
image = models.CharField(max_length=100, null=True)
categories = models.ArrayModelField(
model_container=Category,
model_form_class=CategoryForm
)
specifications = models.ArrayModelField(
model_container=Specifications,
model_form_class=SpecificationsForm
)
description = models.CharField(max_length=1000)
reviews = models.ArrayModelField(
model_container=Reviews,
model_form_class=ReviewsForm
)
drizzly = models.BooleanField(default=False)
complete = models.BooleanField(default=False)
comment = models.CharField(max_length=500)
click_count = models.IntegerField()
class Meta:
# Latest by ascending updated_at.
get_latest_by = "updated_at"
# This will ensure the objects returned are ordered latest to earliest.
ordering = ['-updated_at']
serializer.py
class ProductsSerializer(serializers.ModelSerializer):
class Meta:
model = Products
exclude = ['created_at', 'updated_at']
views.py
class ProductsViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows groups to be viewed or edited.
"""
# Using Products.objects.latest() should return the latest using
# the updated_at DateTimeField.
# Note this will raise `Models.DoesNotExist` if there is no object.
# Using the Model._meta.ordering the queryset should be ordered by
# the `latest` first or you can also use
# `Model.objects.order_by('-updated_at')`
queryset = Products.objects.all()
serializer_class = ProductsSerializer
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.