I am sure this one is straight forward but I cannot seem to get my head around it.
I have "Users" who can post "Posts" on my site.
Each user can follow other users.
The idea is to display all the posts posted by the users that current user is following.
Example : Foo followed Bar and Baz. I need to retrieve all the posts from Bar and Baz.
Bar = Post.objects.filter(user=3)
Baz = Post.objects.filter(user=4)
totalpost= list(chain(Bar, Baz))
print(totalpost)
On this occasion, when both variables userXposts and temp are hardcoded, I can easily retrieve ONE list of QuerySets neeatly by chaining both QuerySets.
However, I cannot have those hardcoded. As such, I am attempted to loop through each user posts and add it in a list since my user can follow X amount of users :
QuerySet = Profile.objects.filter(follower=1)
for x in QuerySet:
userXposts = Post.objects.filter(user=x.user.id)
temp = userXposts
totalpost= list(chain(userXposts, temp))
temp = []
print("Totalpost after union of userpost and temp: ", totalpost)
Here, Profile.objects.filter(follower=1) return two sets of QuerySets, one for Baz and one for Bar.
The problem that I have so far is that totalpost endup being a "list of list" (I believe) which forces me to call totalpost[0] for Bar posts and totalpost[1] for Baz posts.
Since I am attempting to use Pagination with Django, I am forced to pass ONE Variable only in p= Paginator(totalpost, 200)
Would you be able to assist in the loop so that I can fetch the data for the first user, add it to a variable, then go to the second user and ADD the second QuerySet data to the list where the First User data is?
Thanks a lot !
EDIT :
Here are the Models :
class User(AbstractUser):
pass
class Profile(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
following = models.ManyToManyField(User, blank=True, related_name="following_name")
follower = models.ManyToManyField(User, blank=True, related_name="follower_name")
def __str__(self):
return f'"{self.user.username}" is followed by {self.follower.all()} and follows {self.following.all()}'
class Post(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
timestamp = models.DateTimeField(default=datetime.now)
post = models.CharField(max_length=350, null=True, blank=True)
like = models.ManyToManyField(User, blank=True, related_name="like_amount")
def __str__(self):
return f'#{self.id}: "{self.user.username}" posted "{self.post}" on "{self.timestamp}". Like : "{self.like.all()}" '
Post.objects.filter(user__ following_name__id=1)
Related
In the forms.py I have a short piece of code which loads the data, but only after I edit print("hello") in it.
The code as follows:
models.py:
class CreateAssignment(models.Model):
user = models.ForeignKey(User, editable=False, blank=True, null=True)
progress = models.CharField(max_length=254, editable=False, blank=True, null=True)
class SetAssignment(models.Model):
mechanic = models.ForeignKey(User, editable=False, blank=True, null=True)
assignment = models.IntegerField(blank=True, null=True)
The mechanic is a permission, plus this mechanic's ID will show in the url of the website, when you will try to set an assignment for this mechanic.
forms.py:
class SetAssignmentForm(forms.ModelForm):
ASSIGNMENT_CHOICES = ()
for item in CreateAssignment.objects.all():
if item.progress == 'Scheduling':
user = User.objects.get(id=item.user_id).username
ASSIGNMENT_CHOICES += (
(item.id, user + ' - ' + str(item.id)),
)
assignment = forms.ChoiceField(choices=ASSIGNMENT_CHOICES, help_text='This is the assignment that you want to apply to this mechanic.')
class Meta:
model = SetAssignment
fields = ('assignment', )
The user_id in this situation is the user that has been set in the CreateAssignment model.
Now the issue is:
The for loop in the SetAssignmentForm works, but it loads data after I put a print in it or when I remove the print from it. Which of course shouldn't really affect the code.
Is there something I'm overlooking? I've been programming in Python Django for 8 weeks now, so if this is a basic program failure, please refer me to a page, because I haven't been able to find any information on this issue.
Thanks for the help.
For the ones that want to know:
views.py:
#login_required
def set_assignment(request):
form = SetAssignmentForm()
id = request.GET.get('id')
user_results = User.objects.filter(pk=id).values()
return render(request, 'pages/set_assignment.html', {'form': form, 'user_results': user_results})
Gif so you can visually see what's happening:
https://drive.google.com/open?id=1u7gfdiS7KitQWNVuvQEEOFJ9wD3q9rY6
You must not write code like this at class level. Anything at that level is only executed once, at definition time - ie when the class is first imported.
If you need to make the values dynamic, you should put the logic inside the __init__ method:
class SetAssignmentForm(forms.ModelForm):
assignment = forms.ChoiceField(choices=[], help_text='This is the assignment that you want to apply to this mechanic.')
def __init__(self, *args, **kwargs):
super(SetAssignmentForm, self).__init__(*args, **kwargs)
items = CreateAssignment.objects.filter(progress='Scheduling').select_related('user')
choices = [(item.id, '{} - {}'.format(item.id, item.user.username)) for item in items]
self.fields['assignment'].choices = choices
(Note, your query logic was very inefficient; my code only hits the database one time.)
However, here you don't even need to do that, because Django already has a form field - ModelChoiceField - that takes its values from the database. You can use a custom subclass of that to show the representation:
class AssignmentField(forms.ModelChoiceField):
def label_from_instance(self, item):
return (item.id, '{} - {}'.format(item.id, item.user.username))
class SetAssignmentForm(forms.ModelForm):
assignment = forms.AssignmentField(queryset=CreateAssignment.objects.filter(progress='Scheduling').select_related('user'))
I'm trying to do a function that allow a user to follow another one. the problem is when I'm adding a new user to the "followings" the user that follow another user is also added in the following list of the followed user. For example if user a follow user b I will have that:
view.py
def follow_test(request):
name = request.POST.get('name', '')
user_followed = Dater.objects.get(username=name)
current_user = Dater.objects.get(id=request.user.id)
print "Current", current_user.followings.all() # display []
print "Followed", user_followed.followings.all() # display []
current_user.followings.add(user_followed)
print "Current", current_user.followings.all() # display <Dater: b>
print "Followed", user_followed.followings.all() # display <Dater: a>
model.py:
followings = models.ManyToManyField('self', blank=True)
I would like the user b only to be add in the followings of a
By default, many-to-many relationships on self are symmetrical. If you don't want this, set symmetrical to False:
followings = models.ManyToManyField('self', blank=True, symmetrical=False)
See the docs
Just set related_name="followed_by" for the many to many field. That would assign the reverse mapping to followed_by
followings = models.ManyToManyField('self', blank=True, symmetrical=False, related_name='followed_by')
I'm not sure where to start. Right now, the user can press like as many times they want and it'll just add up the total likes for that tweet.
models.py
class Howl(models.Model):
author = models.ForeignKey(User, null=True)
content = models.CharField(max_length=150)
published_date = models.DateTimeField(default=timezone.now)
like_count = models.IntegerField(default=0)
rehowl_count = models.IntegerField(default=0)
def get_absolute_url(self):
return reverse('howl:index')
def __str__(self):
return self.content
views.py
class HowlLike(UpdateView):
model = Howl
fields = []
def form_valid(self, form):
instance = form.save(commit=False)
instance.like_count += 1
instance.save()
return redirect('howl:index')
Django Twitter clone. How to restrict user from liking a tweet more than once?
As well as tracking how many Likes a post has, you'll probably also want to track who has "Liked" each post. You can solve both of these problems by creating a joining table Likes with a unique key on User and Howl.
The unique key will prevent any User from doing duplicate likes.
You can do this in Django with a ManyToManyField, note that since this means adding a second User relationship to Howl, we need to disambiguate the relationship by providing a related_name
Eg:
class Howl(models.Model):
author = models.ForeignKey(User, null=True, related_name='howls_authored')
liked_by = models.ManyToManyField(User, through='Like')
# ...rest of class as above
class Like(models.Model):
user = models.ForeignKey(User)
howl = models.ForeignKey(Howl)
class Meta:
unique_together = (('user', 'howl'))
like_count count then becomes redundant, since you can use Howl.liked_by.count() instead.
The other benefit of this is that it allows you to store information about the Like - eg when it was added.
An idea could be adding a column to your table named likers and before incrementing like_counts check if the models.likers contains the new liker or not. If not increment the likes, if yes don't.
Changed liked_count in my models.py to
liked_by = models.ManyToManyField(User, related_name="likes")
views.py
class HowlLike(UpdateView):
model = Howl
fields = []
def form_valid(self, form):
instance = form.save(commit=False)
instance.liked_by.add(self.request.user)
instance.like_count = instance.liked_by.count()
instance.save()
return redirect('howl:index')
index.html
{{howl.liked_by.count}}
I was introduced to Python and Django about two weeks ago, so bear with me. I should also say now that I am using Django 1.6 and Python 3.3.
My project is an order management system. Here's how it works: A customer comes into a store and orders an item. That item is put in an order, which is idle until the employee places the order with a supplier. Basically, I have an Order table, which collects information like customer_name, order_date, status, etc. Then I have an EmployeeOrder table (1-1 relationship with Order) which has all of the elements of an Order, but also takes in employee_placed and employee_order_date (pretty much just extends Order).
What I'm trying to do is write code so that when the user selects which customer Order is being fulfilled by placing an EmployeeOrder, that customer Order's information is displayed. I don't really care how it is displayed right now, a pop up will work just fine. I just don't know how to do it and I haven't come across it anywhere. Right now the drop down box just displays Order 1, Order 2, etc. The user isn't going to remember which items were included in which order, so that's why I want the order information to be shown. Anyway, here's my code so far:
models.py
class Order(models.Model):
customer_order_date = models.DateTimeField('Date helped')
customer_placed = models.ForeignKey(Customer)
employee_helped = models.ForeignKey(Employee)
STATUS_OF_ORDER = (
('IDLE', 'Not yet ordered'),
('SHIP', 'Awaiting delivery'),
('PICK', 'Ready for pickup'),
('UNAV', 'Unavailable for order'),
('BACK', 'Backordered - awaiting delivery'),
('CANC', 'Canceled by customer'),
('ARCH', 'Fulfilled - archived'),
)
status = models.CharField(max_length=4, choices=STATUS_OF_ORDER,
default='IDLE', editable=False)
paid = models.BooleanField('Paid', default=False)
ship = models.BooleanField('Ship', default=False)
comments = models.CharField(max_length=200, blank=True, null=True)
item = models.ManyToManyField(Item)
def __str__(self):
return 'Order ' + str(self.id)
def is_idle(self):
return self.status == 'IDLE'
class EmployeeOrder(models.Model):
order = models.OneToOneField(Order, primary_key=True,
limit_choices_to={'status': 'IDLE'})
employee_order_date = models.DateTimeField('Date ordered')
employee_placed = models.ForeignKey(Employee)
admin.py
class OrderAdmin(admin.ModelAdmin):
list_display = ('customer_order_date', 'customer_placed')
raw_id_fields = ('customer_placed', 'item')
class EmployeeOrderAdmin(admin.ModelAdmin):
list_display = ('employee_order_date', 'employee_placed')
Any and all help is appreciated as I still admit that I am a total noob when it comes to Python and Django!
It sounds to me like you want an employee to be able to use the admin site to create an employee order from a customer order. I think it could be as simple as adding a raw ID field for the customer order. That is, I think you can just change EmployeeOrderAdmin like so:
class EmployeeOrderAdmin(admin.ModelAdmin):
list_display = ('employee_order_date', 'employee_placed')
raw_id_fields = ('order',)
Now when an employee creates an employee order, they will be able to use the OrderAdmin page to find the order they want.
Additionally, suppose you want that pop-up window to display the orders in a particular way. In that case, keep in mind that requests to display that pop-up window will contain an additional GET parameter called pop. You could:
class OrderAdmin(admin.ModelAdmin):
def queryset(self, request):
qs = super(ActiveOfferAdmin, self).queryset(request)
if request.GET.get('pop'):
return qs.order_by(...)
return qs
I am searching of a method to obtain html forms from some one-to-many relations, like order-lineorder, invoice-lineinvoice, etc.
Let me an example:
# models.py
class Order(models.Model):
date = models.DateTimeField()
number = models.IntegerField(default=0)
class LineOrder(models.Model):
description = models.TextField()
price = models.FloatField()
order = models.ForeignKey(Order)
# views.py
def order_form(request):
form = OrderForm()
table_lineorder = LineOrderTable([])
RequestConfig(request).configure(table)
return render(request, "order_form.html", {"form": form, "table": table_lineorder})
Then, I want to obtain the order template with "generic attributes" (date, number), and a table list (originally empty) of lines order. Add some action like add, edit and remove must be possible.
I think that a solution like django-tables2 is possible, but I can't add rows dinamically, I think.
Thanks in advice.
[EDIT]
I have found the solution. It is django-dynamic-formset
I'm not quite clear about your question, but I guess this might be what you want:
class Order(models.Model):
date = models.DateTimeField()
number = models.IntegerField(default=0)
items = model.ManyToManyField(Item)
class Item(models.Model):
description = models.TextField()
price = models.FloatField()
It should be equivalent to one-to-many if you don't assign one Item to multiple Orders.