I am building a social media website. On the profile page and home page are different posts. Each can have multiple images. I created a different model for images and set ForeignKey to Post model. The form for uploading text and images works fine because the images attach to each post in the database.
However, I am having issues writing the views code for the page they are to display. I am getting just text with no images.
I am trying to add an Id to each post in the views but I have no idea how to do that since they are all in one page and therefore have no separate urls.
I don't know if that is the right approach.
models.py
class Tweets(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
note = models.TextField(blank=False,)
date_posted = models.DateTimeField(auto_now_add=True)
url = models.URLField(max_length=200, blank=True)
likes = models.IntegerField(default=0)
def __str__(self):
# if len(self.note) > 60:
# return f"{self.note[:60]}... --- (Posted {self.when_tweeted} ago) by [{self.profile.name}]"
# if self.when_tweeted.title() == "Just Now":
# return f"{self.note[:60]}... --- (Posted {self.when_tweeted}) by [{self.profile.name}], {self.likes} likes"
# else:
# if self.when_tweeted == "Just Now":
# return f"{self.note[:60]}... --- (Posted {self.when_tweeted}) by [{self.profile.name}]"
# return f"{self.note} --- (Posted {self.when_tweeted} ago) by [{self.profile.name}]"
return f"{self.note}({self.id})"
class Meta:
ordering = ['-date_posted']
verbose_name_plural = 'Tweets'
#property
def tweet_id(self):
return self.id
class Images(models.Model):
tweet = models.ForeignKey(Tweets, on_delete=models.CASCADE, related_name='images')
image = models.ImageField(blank=True, upload_to='image/tweets_image')
class Meta:
verbose_name = 'Image'
verbose_name_plural = 'Images'
def __str__(self):
return self.image.url
views.py
def profile_index(request, user_id, *args, **kwargs):
users = User.objects.all()
profiles = Profile.objects.all()
user = get_object_or_404(User, id=user_id)
profile = get_object_or_404(Profile, id=user_id)
tweets = Tweets.objects.all().filter(user=user)
id_list = []
for t in tweets:
id=t.id
print(id)
id_list.append(id)
print(id_list)
target_tweet = get_object_or_404(Tweets, id=id)
tweet_images = target_tweet.images.all()
context = {
'user': user,
'profile': profile,
'tweets': tweets,
'users': users,
'profiles': profile,
'target_tweet': target_tweet,
'tweet_images': tweet_images
}
return render(request, 'twee/profile_index.html', context)
profile.html
{% if tweet == target_tweet %}
{% for img in tweet_images %}
<img class="post-image" src="{{ img.image.url }}" alt="">
{% endfor %}
{% endif %}
Related
am working on a Django project where showing the details of post and amount
here is my models.py of post
class Loader_post(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE ,related_name="Loader")
pick_up_station = models.CharField(max_length=150)
destination_station = models.CharField(max_length=150)
sender_name = models.CharField(max_length=150)
phone_number = PhoneNumberField(null=False, blank=False, unique=True)
receiver_name = models.CharField(max_length=150)
def __str__(self):
return self.user.username
def get_absolute_url(self):
return reverse("Loader:my_job", kwargs={"pk": self.pk})
this is my second models which I inherit Loader post
class price(models.Model):
my_post = models.ForeignKey(Loader_post, related_name='prices',on_delete=models.CASCADE,
null=True, default='')
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, null=True, default='')
driver_price = models.CharField(max_length=150, null=True)
driver_name = models.CharField(max_length=150, null=True)
approved_price = models.BooleanField(default=False)
status = models.BooleanField(default=False)
def get_absolute_url(self):
return reverse("Driver:Driverview")
def __str__(self):
return self.driver_price
this is the view.py of both list and details view
class offer_view(ListView, SelectRelatedMixin):
context_object_name = 'offern'
model = Loader_post
template_name = "offer.html"
def get_queryset(self):
qs = Loader_post.objects.filter(user=self.request.user)
return qs
class offer_view_detail(DetailView):
context_object_name = 'offernew'
model = Loader_post
template_name = "offer_detail.html"
here is my HTML page of list view ...when someone clicks on it it shows the detail of next post
offer.html
{% for my in offern %}
{{my.sender_name}} {% endfor %}
and when someone clicks on its route to the detail page .. but it shows template doesn't exist
this is my detail page ie. offer_details.hml
<p>{{offernew.sender_name}}</p>
<p>{{offernew.receiver_name}}</p>
{% for x in offernew.prices.all %}
<p>
<p>{{x.driver_name}}</p>
</p>
and this is urls.py
path('offerdetail/<int:pk>', views.offer_view_detail.as_view(),name="offerdetail"),
path('offer/', views.offer_view.as_view(), name="offer"),
Following on from comments,
In you ListView,
{{my.sender_name}}
here, the url specified is not defined in your urls.py, that's why it was showing no template doesn't exist, changing to this would solve this.
{{my.sender_name}}
Now, To show prices model in your DetailView, i would do something like this.
class offer_view_detail(DetailView):
context_object_name='offernew'
model = Loader_post
template_name = "offer_detail.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['price_model'] = self.object.prices.all()
return context
and In your Template
<p>{{offernew.sender_name}}</p>
<p>{{offernew.receiver_name}}</p>
{% for x in offernew.price_model %}
<p>{{x.driver_name}}</p>
{% endfor %}
Django Docs for DetailView
How can I display the list of users with the count of total number of posts made by them in a separate HTML page ?
models.py
class Post(models.Model):
author = models.ForeignKey(User.request, on_delete = models.CASCADE)
title = models.CharField(max_length=100)
text = models.TextField()
slug = models.SlugField(unique=True, blank=True, default=uuid.uuid1)
created_date = models.DateTimeField(default=timezone.now)
likes = models.ManyToManyField(User, related_name='post_likes', blank = True)
def get_like_url(self):
return reverse("posts:like-toggle", kwargs={"slug": self.slug})
def get_api_like_url(self):
return reverse("posts:like-api-toggle", kwargs={"slug": self.slug})
def get_absolute_url(self):
return reverse("post_detail",kwargs={'pk':self.pk})
def __str__(self):
return self.title
def count_posts_of(user):
return Post.objects.filter(author=user).count()
You have to learn MVC architecture(MVT in django).
As a beginner first create a sample project to understand this - https://docs.djangoproject.com/en/2.0/intro/tutorial01/
Learn how models.py are written - https://docs.djangoproject.com/en/2.0/topics/db/models/
and how to writeviews.py - https://docs.djangoproject.com/en/2.0/topics/class-based-views/
Then connect them in urls.py - https://docs.djangoproject.com/en/2.0/topics/http/urls/
This is my solution at the moment, but it could be done differently.
First, add count_posts_of method to your User model whatever it is.
For instance I myself created a user model and add this method to it as following:
models.py
class User(models.Model):
name = models.CharField(max_length=100, blank=True, null=True)
#property
def count_posts_of(self):
return self.post_set.all().count()
now in the view pass all the users as context:
views.py
def user_post(request):
context = {'users': User.objects.all()}
return render(request, 'future/user_post_view.html', context)
and finally in the template show the user and their posts' count:
user_post_view.html
{% for user in users %}
{{ user.name }} :
{{ user.count_posts_of }},
{% endfor %}
I am able to delete a users' posts (tweets), but when I do it ends up deleting all of that user's tweets when I only want to delete one at a time, I think it has something to do with the way I am querying the users tweets but I am not sure. I am using Django 1.8.
models.py
from django.db import models
from django.contrib.auth.models import User
import tagging
from tagging.registry import register as tagging_
import os
def get_image_path(instance, filename):
return os.path.join('photos', str(instance.user.id), filename)
class UserProfile(models.Model):
user = models.OneToOneField(User)
bio = models.CharField(max_length=120, blank=True, verbose_name='Biography')
follows = models.ManyToManyField('self', related_name='followers', symmetrical=False, blank=True) #reverse related relations, or through
theme = models.ImageField(upload_to=get_image_path, blank=True)
profile_picture = models.ImageField(upload_to=get_image_path, blank=True)
def __str__(self):
return self.bio
class Tweet(models.Model):
userprofile = models.ForeignKey(UserProfile)
tweets = models.TextField(max_length=120)
date = models.DateTimeField()
def json_feat(self):
return{
'title': self.tweets,
}
def __str__(self):
return self.tweets
tagging_(Tweet)
views.py
def delete_tweet(request, user_id):
data = {'You deleted your tweet'}
user = get_object_or_404(User, pk=user_id)
user_profile = get_object_or_404(UserProfile, user=user)
get_users_tweets = Tweet.objects.filter(userprofile=user_profile)
remove_tweet = get_users_tweets.delete()
return JsonResponse(data, safe=False)
template
{% for tweets in tweet %}
{{ tweets.userprofile.user }} | {{ tweets }} | {{ tweets.date }} | <a href='{% url 'delete_tweet' user_id=user.id %}'>Delete </a> <br />
{% endfor %}
url
url(r'^delete/(?P<user_id>[\d]+)/$', views.delete_tweet, name='delete_tweet'),
get_users_tweets = Tweet.objects.filter(userprofile=user_profile)
Will give you all the tweets written by the specified user -> all of them are deleted. Which one do you want to delete? You need to specify that.
EDIT:
(after specifying what the OP wants to do in the comments)
Update your url to:
url(r'^delete/(?P<tweet_id>[\d]+)/$', views.delete_tweet, name='delete_tweet'),
...and your views.py to:
def delete_tweet(request, tweet_id):
data = {'You deleted your tweet.'}
tweet = Tweet.objects.filter(pk=tweet_id)
tweet.delete()
return JsonResponse(data, safe=False)
You need to add tweet id in your URL
url(r'^delete/(?P<user_id>[\d]+)/(?P<tweet_id>[\d]+)$', views.delete_tweet, name='delete_tweet'),
Then your view will look like this
def delete_tweet(request, user_id,tweet_id):
data = {'You deleted your tweet'}
user = get_object_or_404(User, pk=user_id)
user_profile = get_object_or_404(UserProfile, user=user)
get_users_tweets = Tweet.objects.filter(userprofile_id=user_id,id=tweet_id)
remove_tweet = get_users_tweets.delete()
return JsonResponse(data, safe=False)
This will remove that particular tweet regarding that user.
python 3.4.2
django 1.7.1
postgres 9.4
I am attempting to query data from postgres and send it to the template for rendering.
I've included the models, views, urls.py, and the media page
I think the issue is in views.py, and the contextDict var I send to the template.
What should be happening:
user hits index.html and clicks a link to view more information about a media asset
index.html loads the views.py 'media' function
media function captures the slugify URL and uses it to query the DB
the 'media' function in views.py loads the data into variables
the 'media' function passes the request, template url, and variables to the template
the template processes the variables and sends the page to the users client
what is happening
user hits index.html and clicks link to view more information about the media asset
index.html loads the views.py mdia function
the user sees a rendered page with text "The specified project {{projectSlugTitle}} does not exist"
what I think the problem is
step 3-6 is f**** up, I think the problem lies either in my query to the DB, or how i'm passing the data to the template
model:
from django.db import models
from django.utils import timezone
from django.template.defaultfilters import slugify
#table for media files: audio, video, design
class Media(models.Model):
#choicesConstants
#type
MEDIATYPE_FILM = 'MEDIATYPE_FILM'
MEDIATYPE_AUDIO = 'MEDIATYPE_AUDIO'
MEDIATYPE_DESIGN = 'MEDIATYPE_DESIGN'
#category
MEDIACATEGORY_MAJOR = 'MEDIACATEGORY_MAJOR'
MEDIACATEGORY_INDIE = 'MEDIACATEGORY_INDIE'
#genre
MEDIAGENRE_RAP = 'MEDIAGENRE_RAP'
MEDIAGENRE_ROCK = 'MEDIAGENRE_ROCK'
MEDIAGENRE_TECHNO = 'MEDIAGENRE_TECHNO'
#choicesList
choicesType = (
(MEDIATYPE_FILM,'Video'),
(MEDIATYPE_AUDIO,'Audio'),
(MEDIATYPE_DESIGN,'Design'),
)
choicesCategory = (
(MEDIACATEGORY_INDIE,'Indie'),
(MEDIACATEGORY_MAJOR,'Major'),
)
choicesGenre = (
(MEDIAGENRE_RAP,'Rap'),
(MEDIAGENRE_ROCK,'Rock'),
(MEDIAGENRE_TECHNO,'Techno')
)
#boolean
mediaPublished = models.BooleanField(default=True)
#char fields
title = models.CharField(max_length=256,blank=True)
type = models.CharField(max_length=256,choices=choicesType, default=MEDIATYPE_FILM)
category = models.CharField(max_length=256,choices=choicesCategory,default=MEDIACATEGORY_MAJOR)
genre = models.CharField(max_length=256,choices=choicesGenre,default=MEDIAGENRE_TECHNO)
#integer fields
views = models.IntegerField(default=0)
upVotes = models.IntegerField(default=0)
downVotes = models.IntegerField(default=0)
#date fields
dateAdded = models.DateTimeField(default=timezone.now)
datePublished = models.DateTimeField(blank=True,null=True)
dateDePublished = models.DateTimeField(blank=True,null=True)
#urlfields
intUrl = models.URLField(blank=True)
extUrl = models.URLField(blank=True)
#email fields
mediaEmail = models.EmailField(max_length=254,blank=True)
#decimalFields
mediaB2bPrice = models.DecimalField(max_digits=20,decimal_places=2,default=0)
mediaB2cPrice = models.DecimalField(max_digits=20,decimal_places=2,default=0)
#slugFields
slug1 = models.SlugField()
#functionUtility
def __str__(self):
return self.title
#functionMath
def totalVotes(self):
return int(self.upVotes)+int(self.downVotes)
def percentUpVotes(self):
return int(self.upVotes)/int(self.totalVotes)
def percentDownVotes(self):
return int(self.downVotes) / int(self.totalVotes)
def save(self, *args,**kwargs):
self.slug1 = slugify(self.title)
super(Media, self).save(*args, **kwargs)
#metaData
class Meta:
ordering = ['dateAdded','title']
get_latest_by = 'dateAdded'
verbose_name = 'Media'
verbose_name_plural = 'Media'
#tablef for projects, contain multiple media files
class Project(models.Model):
#manyToMany relationships
media = models.ManyToManyField(Media,null=True,blank=True)
#boolean
projectPublished = models.BooleanField(default=True)
#charFields
title = models.CharField(blank=True,max_length=256)
#textFields
projectDescription = models.TextField(blank=True)
#email fields
projectEmail = models.EmailField(max_length=254,blank=True)
#dateFields
dateCreated = models.DateTimeField(default=timezone.now)
datePublished = models.DateTimeField(blank=True,null=True)
#decimalFields
projectB2bPrice = models.DecimalField(max_digits=20,decimal_places=2,default=0)
projectB2cPrice = models.DecimalField(max_digits=20,decimal_places=2,default=0)
#slugFields
slug1 = models.SlugField()
#functionsUtility
def __str__(self):
return self.title
def save(self, *args, **kwargs):
self.slug1 = slugify(self.title)
super(Project, self).save(*args, **kwargs)
#metaData
class Meta:
ordering = ['dateCreated','title']
get_latest_by = 'dateAdded'
verbose_name = 'Project'
verbose_name_plural = 'Projects'
view:
def project(request,theProjectSlug):
contextDict = {}
try:
#retrieve the project with the matching slug name
project = Project.objects.get(slug1=theProjectSlug)
contextDict['projectName'] = project.title
#retrieve all of the associated media files of the project above
mediaFiles = Media.objects.all().filter(project=project)
#add mediaFiles to contextDict,add the project to the contextDict
contextDict['mediaFilesOfProject'] = mediaFiles
contextDict['project'] = project
except Project.DoesNotExist:
pass
return render(request, 'famecity/media.html', contextDict)
urls.py:
urlpatterns = patterns('',
url(r'^$',views.index,name='index'),
url(r'^about/',views.about,name='about'),
url(r'^media/(?P<theProjectSlug>[\w\-]+)/$',views.project,name='project')
)
the rendered page:
<!DOCTYPE html>
<html>
<head>
<title>Fame.city Projects
</title>
</head>
<body>
<h1>
projectName: {{ projectName }}<br/>
mediaFilesOfProject: {{mediaFilesOfProject}}<br/>
project: {{project}}<br/>
</h1>
{% if project %}
{% if media %}
<ul>
{% for mFile in media %}
<li>
{{mFile.title}}
</li>
{% endfor %}
</ul>
{% else %}
<strong>No media files exist</strong>
{% endif %}
{% else %}
The specified project {{projectSlugTitle}} does not exist
{% endif %}
</body>
</html>
Found the issue
I was querying the Project table instead of the Media table
when the user hits index.html and clicks the media link, my code above sent create an SQL to the Project table, and the error cascades from there because of the subsequent lines are based on the initial value of the first variable.
I'm using Pinax to create a new project. For this project I needed to create a new app 'Business' which is much like Profiles but they wanted to keep everything seperate for Businesses.
I'm trying to have the admin be able to change the logo or "avatar" for the business profile. Im using the ImageModel class from Photologue to control the image upload, etc but I ran into a problem. When going through the form, the form goes through and redirects but the image doesn't actually get updated. When you go through the django admin, the image uploads fine.
If someone could take a look and see if something is missing, I've been staring at it for too long, so I need a fresh pair of eyes.
Business Models.py
class Business(models.Model):
name = models.CharField(verbose_name="Name", max_length=140)
desc = models.TextField(verbose_name="Description", null=True, blank=True)
bus_type = models.CharField(verbose_name="Business Type", choices=BUSINESS_TYPES, max_length=20)
location = models.CharField(_("location"), null=True, blank=True, max_length=200)
website = models.URLField(_("website"), null=True, blank=True, verify_exists=False)
created_by = models.ForeignKey(User, related_name="Created By")
admin = models.ManyToManyField(User, related_name="Admin User", null=True, blank=True)
followers = models.ManyToManyField(User, related_name="Followed by", null=True, blank=True)
date_added = models.DateField(verbose_name="Date Added")
class Meta:
verbose_name = "Business"
verbose_name_plural = "Businesses"
def __unicode__(self):
return self.name
class BusinessLogo(ImageModel):
business = models.ForeignKey(Business, related_name="Business Association")
My views.py
#login_required
def changeLogo(request, bus_id):
user = request.user
b = get_object_or_404(Business, pk = bus_id)
if request.method == 'POST':
form = ChangeLogoForm(request.POST, request.FILES, instance = b)
if form.is_valid():
biz_logo = form.save(commit=False)
biz_logo.save()
return HttpResponseRedirect('/')
else:
form = ChangeLogoForm()
return render_to_response('business/changelogo.html',
{'user': user, 'form':form, 'b':b}, context_instance=RequestContext(request))
Forms.py
class ChangeLogoForm(ModelForm):
class Meta:
model = BusinessLogo
def save(self, force_insert=False, force_update=False, commit=True):
f = super(ChangeLogoForm, self).save(commit=False)
if commit:
f.save()
print "form save method was called with commit TRUE"
return f
And finally my changelogo.html
...
{% block body %}
<h1>Change Logo</h1>
<form method="POST" action="" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Upload">
</form>
{% endblock %}
...
Thanks everyone, for taking a look.
Steve
The ChangeLogoForm's model is BusinessLogo, but when calling it's constructor you pass it a Business instance:
b = get_object_or_404(Business, pk = bus_id)
...
form = ChangeLogoForm(request.POST, request.FILES, instance = b)
(And you should probably use a OneToOneField field instead of ForeignKey)