I'm making an forum using this tutorial http://lightbird.net/dbe/forum2.html and I encountered an error .
When I click edit profile , it suppose to point to this page instead I get an error(below)
DoesNotExist at /forum/profile/1/
UserProfile matching query does not exist.
Request Method: GET
Request URL: http://127.0.0.1:8000/forum/profile/1/
Django Version: 1.4.3
Exception Type: DoesNotExist
Exception Value:
UserProfile matching query does not exist.
Traceback Switch to copy-and-paste view
C:\djcode\mysite\forum\views.py in profile
profile = UserProfile.objects.get(user=pk)
I think this error mean , django can't receive my admin login .
This is part of my fbase.html
Edit profile
which point to my URLconf.
from django.conf.urls import patterns,include,url
from django.contrib import admin
from django.conf import settings
urlpatterns = patterns('forum.views',
url(r'^$','main',name='main'),
url(r"^forum/(\d+)/$", "forum",name ="forum"),
url(r"^thread/(\d+)/$","thread",name = "thread"),
url(r"^post/(new_thread|reply)/(\d+)/$", "post",name = "post"),
url(r"^reply/(\d+)/$", "reply" , name ="reply"),
url(r"^new_thread/(\d+)/$", "new_thread" , name ="new_thread"),
url(r"^profile/(\d+)/$", "profile",name= "profile"),
)
and into my view function
def profile(request, pk):
"""Edit user profile."""
profile = UserProfile.objects.get(user=pk)
img = None
if request.method == "POST":
pf = ProfileForm(request.POST, request.FILES, instance=profile)
if pf.is_valid():
pf.save()
# resize and save image under same filename
imfn = pjoin(MEDIA_ROOT, profile.avatar.name)
im = PImage.open(imfn)
im.thumbnail((160,160), PImage.ANTIALIAS)
im.save(imfn, "JPEG")
else:
pf = ProfileForm(instance=profile)
if profile.avatar:
img = "/media/" + profile.avatar.name
return render_to_response("forum/profile.html", add_csrf(request, pf=pf, img=img))
This is my models.py
from django.db import models
from django.contrib.auth.models import User
from django.contrib import admin
from string import join
from mysite.settings import MEDIA_ROOT
class Forum(models.Model):
title = models.CharField(max_length=60)
def __unicode__(self):
return self.title
def num_posts(self):
return sum([t.num_posts() for t in self.thread_set.all()])
def last_post(self):
if self.thread_set.count():
last = None
for t in self.thread_set.all():
l = t.last_post()
if l:
if not last: last = l
elif l.created > last.created: last = l
return last
class Thread(models.Model):
title = models.CharField(max_length=60)
created = models.DateTimeField(auto_now_add=True)
creator = models.ForeignKey(User, blank=True, null=True)
forum = models.ForeignKey(Forum)
def __unicode__(self):
return unicode(self.creator) + " - " + self.title
def num_posts(self):
return self.post_set.count()
def num_replies(self):
return self.post_set.count() - 1
def last_post(self):
if self.post_set.count():
return self.post_set.order_by("created")[0]
class Post(models.Model):
title = models.CharField(max_length=60)
created = models.DateTimeField(auto_now_add=True)
creator = models.ForeignKey(User, blank=True, null=True)
thread = models.ForeignKey(Thread)
body = models.TextField(max_length=10000)
def __unicode__(self):
return u"%s - %s - %s" % (self.creator, self.thread, self.title)
def short(self):
return u"%s - %s\n%s" % (self.creator, self.title, self.created.strftime("%b %d, %I:%M %p"))
short.allow_tags = True
### Admin
class ForumAdmin(admin.ModelAdmin):
pass
class ThreadAdmin(admin.ModelAdmin):
list_display = ["title", "forum", "creator", "created"]
list_filter = ["forum", "creator"]
class PostAdmin(admin.ModelAdmin):
search_fields = ["title", "creator"]
list_display = ["title", "thread", "creator", "created"]
class UserProfile(models.Model):
avatar = models.ImageField("Profile Pic", upload_to="images/", blank=True, null=True)
posts = models.IntegerField(default=0)
user = models.ForeignKey(User, unique=True)
def __unicode__(self):
return unicode(self.user)
You forgot to put pk in your render:
return render_to_response("forum/profile.html", add_csrf(request, pf=pf, 'profile': profile, img=img))
In html:
Edit profile
Related
Apologies if this has already been answered elsewhere. I cannot find an answer which I can retrofit into my situation.
I'm new to django so I feel the problem is me not getting a fundamental grasp of a presumably basic concept here...
Using DRF and pytest-django, i'm trying to be diligent and write tests along the way before it becomes too time consuming to manually test. I can see it snowballing pretty quickly.
The issue I face is when I try to test the creation of a Catalogue, I can't get it to pass an User instance to the mandatory field 'created_by'. The logic works fine when I test manually, but writing the test itself is causing me headaches.
Many thanks in advance!
The error is:
TypeError: Cannot encode None for key 'created_by' as POST data. Did you mean to pass an empty string or omit the value?
Code provided.
# core/models.py
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
email = models.EmailField(unique=True)
# workshop/models.py
from django.conf import settings
from django.db import models
class Catalogue(models.Model):
STATE_DRAFT = 'DRAFT'
STATE_PUBLISHED_PRIVATE = 'PUBPRIV'
STATE_PUBLISHED_PUBLIC = 'PUBPUB'
STATE_CHOICES = [
(STATE_DRAFT, 'Draft'),
(STATE_PUBLISHED_PRIVATE, 'Published (Private)'),
(STATE_PUBLISHED_PUBLIC, 'Published (Public)')
]
company = models.ForeignKey(Company, on_delete=models.PROTECT)
title = models.CharField(max_length=255)
description = models.TextField(null=True, blank=True)
state = models.CharField(
max_length=10, choices=STATE_CHOICES, default=STATE_DRAFT)
created_by = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.PROTECT)
created_on = models.DateTimeField(auto_now_add=True)
def __str__(self) -> str:
return self.title
class CatalogueItem(models.Model):
TYPE_GOODS = 'GOODS'
TYPE_SERVICES = 'SERVICES'
TYPE_GOODS_AND_SERVICES = 'GOODS_AND_SERVICES'
TYPE_CHOICES = [
(TYPE_GOODS, 'Goods'),
(TYPE_SERVICES, 'Services'),
(TYPE_GOODS_AND_SERVICES, 'Goods & Services')
]
catalogue = models.ForeignKey(
Catalogue, on_delete=models.CASCADE, related_name='catalogueitems')
type = models.CharField(
max_length=50, choices=TYPE_CHOICES, default=TYPE_GOODS)
name = models.CharField(max_length=255)
description = models.TextField()
unit_price = models.DecimalField(max_digits=9, decimal_places=2)
can_be_discounted = models.BooleanField(default=True)
def __str__(self) -> str:
return self.name
#property
def item_type(self):
return self.get_type_display()
# workshop/serializers.py
class CatalogueSerializer(serializers.ModelSerializer):
catalogueitems = SimpleCatalogueItemSerializer(
many=True, read_only=True)
created_on = serializers.DateTimeField(read_only=True)
created_by = serializers.PrimaryKeyRelatedField(read_only=True)
class Meta:
# depth = 1
model = Catalogue
fields = ['id', 'title', 'description',
'state', 'catalogueitems', 'created_by', 'created_on']
def create(self, validated_data):
company_id = self.context['company_id']
user = self.context['user']
return Catalogue.objects.create(company_id=company_id, created_by=user, **validated_data)
# workshop/views.py
class CatalogueViewSet(ModelViewSet):
serializer_class = CatalogueSerializer
def get_permissions(self):
if self.request.method in ['PATCH', 'PUT', 'DELETE', 'POST']:
return [IsAdminUser()]
return [IsAuthenticated()]
def get_queryset(self):
user = self.request.user
if user.is_staff:
return Catalogue.objects.prefetch_related('catalogueitems__catalogue').filter(company_id=self.kwargs['company_pk'])
elif user.is_authenticated:
return Catalogue.objects.filter(company_id=self.kwargs['company_pk'], state='PUBPUB')
def get_serializer_context(self):
company_id = self.kwargs['company_pk']
return {'company_id': company_id, 'user': self.request.user}
# workshop/tests/conftest.py
from core.models import User
from rest_framework.test import APIClient
import pytest
#pytest.fixture
def api_client():
return APIClient()
#pytest.fixture
def authenticate(api_client):
def do_authenticate(is_staff=False):
return api_client.force_authenticate(user=User(is_staff=is_staff))
return do_authenticate
# workshop/tests/test_catalogues.py
from core.models import User
from workshop.models import Catalogue
from rest_framework import status
import pytest
#pytest.fixture
def create_catalogue(api_client):
def do_create_catalogue(catalogue):
return api_client.post('/companies/1/catalogues/', catalogue)
return do_create_catalogue
class TestCreateCatalogue:
def test_if_admin_can_create_catalogue_returns_201(self, authenticate, create_catalogue):
user = authenticate(is_staff=True)
response = create_catalogue(
{'title': 'a', 'description': 'a', 'state': 'DRAFT','created_by':user})
assert response.status_code == status.HTTP_201_CREATED
I think you may have a problem with the user that you are using to do the test,
when you call authenticate it returns a client which is not the same as a user.
then you run the authenticate and log in as a generic user. Try making another fixture that creates a user first, authenticate with that user to return the client and then post that user you created to create_catalogue
from django.conf import settings
#pytest.fixture
def create_user() -> User:
return settings.AUTH_USER_MODEL.objects.create(
username="Test User", password="Test Password", email="testuser#example.com"
)
#pytest.fixture
def authenticate(api_client):
def do_authenticate(create_user):
return api_client.force_authenticate(create_user)
return do_authenticate
class TestCreateCatalogue:
def test_if_admin_can_create_catalogue_returns_201(self, authenticate, create_user create_catalogue):
user = authenticate(create_user)
response = create_catalogue(
{'title': 'a', 'description': 'a', 'state': 'DRAFT','created_by':create_user})
assert response.status_code == status.HTTP_201_CREATED
I have a form that gets some fields and tags from users and save the user input data in database:
By the way I am using taggit
this is my model:
from taggit.managers import TaggableManager
class Question(models.Model):
title = models.CharField(max_length=500)
name = models.CharField(max_length=50, default=None)
slug = models.SlugField(max_length=500, unique_for_date='created', allow_unicode=True)
body = models.TextField(max_length=2000)
created = models.DateTimeField(auto_now_add=True)
tags = TaggableManager()
def get_absolute_url(self):
return reverse("questions:question_detail", args=[self.created.year, self.created.month, self.created.day, self.slug])
def __str__(self):
return self.title
and here is my view:
def question_form(request):
new_question = None
if request.method == 'POST':
question_form = QuestionForm(data=request.POST)
if question_form.is_valid():
new_question = question_form.save(commit=False)
new_question.slug = slugify(new_question.title)
new_question.save()
question_form.save_m2m()
else:
question_form = QuestionForm()
return render(request,
'questions/que/form.html',
{'question_form':question_form, 'new_question':new_question})
and my form.py is like this:
from taggit.forms import TagField
class QuestionForm(ModelForm):
class Meta:
model = Question
fields = ('name', 'title', 'body',)
tags = TagField()
my problem is when user enters the tags and other fields everything is saved in database except the tags! Can anyone help me?
I'm attempting to save records into a model using the modelform (this part is working as intended) and delete records from the same model using a checkbox (can't figure this piece out). I am creating a comprehensive view so I'm not creating using a def variable(reqeust, id) function and my intention is to have both POST methods redirect back to the same page. How would I go about deleting a model record using a checkbox and POST? I will add an #login_required decorator later. Here is my code:
models.py:
class ReportDirectory(models.Model):
report_name = models.CharField(max_length=300, unique=True, blank=False)
report_desc = models.TextField()
report_type = models.CharField(max_length=300)
report_loc = models.TextField()
slug = models.SlugField(unique=True, max_length=300)
last_update = models.DateTimeField(null=True)
main_tags = models.CharField(max_length=300)
# Renames the item in the admin folder
def __str__(self):
return self.report_name
class Favorite(models.Model):
directory_user = models.ForeignKey(User, on_delete=models.CASCADE)
user_report = models.ForeignKey(ReportDirectory, on_delete=models.CASCADE)
favorited = models.BooleanField()
def __str__(self):
return str(self.directory_user)+" - "+str(self.user_report)
views.py:
from django.shortcuts import render,redirect
from django.views import generic
from .models import ReportDirectory, Favorite
from django.contrib.auth.models import User
from .forms import FavoriteForm
def report_directory(request):
favorite = Favorite.objects.filter(directory_user=request.user.id, favorited=True)
reports = ReportDirectory.objects.exclude(favorite__directory_user=request.user.id, favorite__favorited=True)
favform = FavoriteForm(initial={'directory_user':request.user,},)
context = {
'reports':reports,
'favorite':favorite,
'favform':favform
}
if request.method =='POST' and 'favorited' in request.POST:
form = FavoriteForm(request.POST)
if form.is_valid():
form.save()
return redirect('/report_directory')
else:
form = FavoriteForm()
elif request.method =='POST' and 'deletefav' in request.POST:
Favorite.objects.filter(id=id).delete()
return redirect('/report_directory')
return render(request, 'counter/report_directory.html',context)
This is my model:
def group_based_upload_to(instance, filename):
return "media/image/lavorazione/{}".format(instance.prestazione.id,)
class ImmaginiLavorazioni(models.Model):
immagine = models.ImageField(upload_to=group_based_upload_to)
prestazione = models.ForeignKey(Listino, on_delete=models.SET_NULL, null=True,
blank=True, default=None, related_name='Listino3')
and my form:
class ImmagineUploadForm(forms.ModelForm):
class Meta:
model = ImmaginiLavorazioni
exclude = ('preventivo', )
I need a view to save an image in a specific path.
The name of path must be the pk of foreign key.
How can I do that?
I use a model of how a blog post works. You can adjust the example on your needs. You should try and avoid saving the location path from a view.
On your models.py:
# Create your models here.
def upload_location(instance, filename):
filebase, extension = filename.split(".")
return "%s/%s" % (instance.id, filename)
class Post(models.Model):
title = models.CharField(max_length=120)
slug = models.SlugField(unique=True)
image = models.ImageField(upload_to=upload_location,
null=True,
blank=True,
height_field="height_field",
width_field="width_field")
height_field = models.IntegerField(default=0)
width_field = models.IntegerField(default=0)
content = HTMLField()
formfield_overrides = {
models.TextField: {'widget': AdminPagedownWidget },
}
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
On your forms.py:
from django import forms
from pagedown.widgets import PagedownWidget
from pagedown.widgets import AdminPagedownWidget
from .models import Post
class PostForm(forms.ModelForm):
content = forms.CharField(widget=PagedownWidget(show_preview=False))
class Meta:
model = Post
fields = [
"title",
"content",
"image"
]
class PostModelForm(forms.ModelForm):
content = forms.CharField(widget=AdminPagedownWidget())
class Meta:
model = Post
fields = '__all__'
And on your settings.py:
MEDIA_URL = "/media/"
MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), "media_cdn")
Here is your view.py:
# Create your views here.
def post_create(request):
if not request.user.is_staff or not request.user.is_superuser:
raise Http404
form = PostForm(request.POST or None, request.FILES or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
messages.success(request, "Succefully Created")
return HttpResponseRedirect(instance.get_absolute_url())
context = {
"form": form,
}
return render(request, "post_form.html", context)
The next code has an example without form but you can modify based on your needs.
Below the settings.py
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.realpath(__file__))
MEDIA_ROOT = os.path.join(BASE_DIR, '../media')
Firstable, I defined the path of the image in the helpers.py
from django.conf import settings
from datetime import datetime
def upload_to_image_post(self, filename):
"""
Stores the image in a specific path regards to date
and changes the name of the image with for the name of the post
"""
current_date = datetime.now()
return '%s/posts/main/{year}/{month}/{day}/%s'.format(
year=current_date.strftime('%Y'), month=current_date.strftime('%m'),
day=current_date.strftime('%d')) % (settings.MEDIA_ROOT, filename)
You could define the image's name with some code like this one. But you have to regard you should have the pk to replace the name of the image
ext = filename.split('.')[-1]
name = self.pk
filename = '%s.%s' % (name, ext)
So, I called the def in my models.py, specifically in the image's field
from django.db import models
from django.utils.text import slugify
from .helpers import upload_to_image_post
class Post(models.Model):
"""
Store a simple Post entry.
"""
title = models.CharField('Title', max_length=200, help_text='Title of the post')
body = models.TextField('Body', help_text='Enter the description of the post')
slug = models.SlugField('Slug', max_length=200, db_index=True, unique=True, help_text='Title in format of URL')
image_post = models.ImageField('Image', max_length=80, blank=True, upload_to=upload_to_image_post, help_text='Main image of the post')
class Meta:
verbose_name = 'Post'
verbose_name_plural = 'Posts'
I hope this helped you
Now this is my models:
def group_based_upload_to(instance, immagine):
return "media/preventivo/{pk}/{image}".format(pk=instance.preventivo.id, image=immagine)
class ImmaginiLavorazioni(models.Model):
immagine = models.ImageField(upload_to=group_based_upload_to)
preventivo = models.ForeignKey(Preventivo, on_delete=models.SET_NULL, null=True, blank=True,
default=None, related_name='Listino3')
And this is my view:
def upload_immagine(request, pk):
member = get_object_or_404(Preventivo, pk=pk)
if request.method == 'POST':
form = ImmagineUploadForm(request.POST or None, request.FILES or None)
if form.is_valid():
newimmagine = form.save(commit=False)
newimmagine.preventivo_id = member.pk
newimmagine.save()
return redirect('preventivo_new2', pk=member.pk)
else:
form = ImmagineUploadForm(request.POST or None, request.FILES or None)
return render(request, 'FBIsystem/upload_immagine.html', {'member': member, 'form': form})
It save in db the file path and the foreign key like:
immagine= media/preventivo/6/image.jpg
preventivo_id = 6
but not create a folder and not save the uploaded image...
I have an Ourteam App that allows you to upload an image, name, title, and social media information for employees. Whenever I create an object the "default.jpg" file is deleted from the media_root.
This is my model:
from django.db import models
from cms.models.pluginmodel import CMSPlugin
from django.utils.translation import ugettext_lazy as _
from smartfields import fields
from smartfields.dependencies import FileDependency
from smartfields.processors import ImageProcessor
from django.template.defaultfilters import slugify
class Employee(CMSPlugin):
# Set Name
name = models.CharField(_('name'), max_length=48)
# Define Slug
slug = models.SlugField(max_length=40, null = False, blank = True)
# Set Title
title = models.CharField(_('title'), max_length=48)
# Set Image upload path and image properties
image_upload_path = 'ourteam/%Y/%m/%d'
image = fields.ImageField(upload_to=image_upload_path,
blank=True, default='ourteam/default.jpg',
dependencies=[
FileDependency(processor=ImageProcessor(
format='JPEG', scale={'max_width': 150, 'max_height': 150}))
])
created = models.DateTimeField(_('created'), auto_now_add=True)
email = models.EmailField(_('email'), max_length=254)
# Social Media
twitter = models.CharField(_('twitter'), max_length=24, blank=True, default='https://www.twitter.com')
linkedin = models.CharField(_('linkedin'), max_length=24,blank=True, default='https://www.linkedin.com')
facebook = models.CharField(_('facebook'), max_length=24,blank=True, default='https://www.facebook.com')
class Meta:
verbose_name = _('employee')
verbose_name_plural = _('employee')
db_table = 'employee'
ordering = ('-created',)
get_latest_by = 'created'
def __unicode__(self):
return u'%s' % self.title
def __str__(self):
return self.name
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Employee, self).save(*args, **kwargs)
def get_all_employees():
all_entries = Employee.objects.all().order_by('created')
return all_entries
def slug(sluggy):
sluggy = sluggy.replace(' ', '-').lower()
return slugify(sluggy)
You should try with that :
def user_directory_path(instance, filename):
# file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
return 'user_{0}/{1}'.format(instance.user.id, filename)
class MyModel(models.Model):
upload = models.FileField(upload_to=user_directory_path)