Django Publishable is_public field - python

So at work we are using django-publish for publishing case studies. Whenever a case study is published, it is viewable by a regular user. However if it is in draft mode, and user is logged in as an admin, on the index page he should be able to see all the case studies, whether published or still in draft mode, that would link to the actual case study pages for each, however for studies in draft mode '?draft' should be appended to the individual url. Hopefully that makes sense.
My problem is that 'is_public' field, inherited from the Publishable class, shows up correctly when viewed by the regular user, however when admin is logged in and is trying to view the page, is_public field always shows up as False, even though it is clearly True in the database.
def get_absolute_url(self):
if self.slug:
if self.is_public:
return reverse('case-study', args=(self.slug,))
else:
return reverse('case-study', args=(self.slug,)) + '?draft'
return reverse('work',)
I have this from the model get_absolute_url method, thus when logged in as admin, every case study has '?draft' appended to it.
I would appreciate any help with this.
This is the full model:
class CaseStudy(Publishable, Sortable):
# Text
title = models.CharField(max_length=100)
subtitle = models.CharField(max_length=100, blank=True, null=True)
description = models.CharField('Summary', max_length=255)
challenge = models.TextField('The Challenge')
solution = models.TextField('Our Solution')
# Images
image = models.ImageField('Thumbnail', upload_to="case-study/thumbs")
header = models.ImageField('Header Image', upload_to="case-study/header")
# Client Meta
client = models.ForeignKey(Client, null=True, blank=True)
expertise = models.ManyToManyField(Expertise)
capability = models.ManyToManyField(Capabilty)
services = models.TextField(blank=True, help_text='One per line')
# Formatting
scheme = models.CharField('Color Palette', max_length=100, choices=COLOR_SCHEMES)
# Display Options
home_page = models.BooleanField('Feature on Home Page?', default=False)
work_page = models.BooleanField('Feature on Work Page?', default=False)
# Meta
slug = models.SlugField()
created = CreationDateTimeField()
modified = ModificationDateTimeField()
class Meta(Publishable.Meta, Sortable.Meta):
verbose_name = 'Case Study/Story'
verbose_name_plural = 'Case Studies'
class PublishMeta(Publishable.PublishMeta):
publish_reverse_fields = ['sections', 'related_projects']
def __unicode__(self):
return u'%s' % self.title
def get_absolute_url(self):
if self.slug:
if self.is_public:
return reverse('case-study', args=(self.slug,))
else:
return reverse('case-study', args=(self.slug,)) + '?draft'
return reverse('work',)

Related

How to update a manytomany field in Django without deleting the previous object?

I have seen this question before, but mine is a bit more restricted in terms of getting the object and filtering.
EDIT - Removed relationship between member and title and changed member and xmlgraph to one to many relationship
I have these classes in models.py:
class Title(models.Model):
title = models.TextField(null=True)
def __str__(self):
return self.title
class XMLGraph(models.Model):
#only one title per graph
title = models.OneToOneField(
to=Title,
blank=True,
null=True,
on_delete=models.CASCADE)
XMLGraph = models.TextField(null=True)
def __str__(self):
return str(self.XMLGraph)
class Member(User):
XMLGraph = models.ForeignKey('XMLGraph',
null=True,
on_delete=models.CASCADE)
def __str__(self):
return self.username
class Profile(models.Model):
user = models.OneToOneField(
to=Member,
blank=True,
null=True,
on_delete=models.CASCADE
)
def __str__(self):
return self.name
One Member can store multiple XMLGraphs which are basically text files stored in the database. I have a functionality where the user can save and save as the XMLGraph.
The save function should create a new object of the XMLGraph if there is nothing in the database or update the current XMLGraph. So, when the user presses save, it should update the data stored in the XMLGraph. So, I took this approach:
Save function in views.py
def saveData(request, user):
if request.method == "POST":
xmlData = request.POST['xml']
member = Member.objects.get(username=user)
XMLGraph.objects.all().delete()
xml, _ = XMLGraph.objects.get_or_create(XMLGraph = xmlData)
member.XMLGraph.add(xml)
return render_to_response("fastcookapp/index.html", content_type="text/xml;")
return HttpResponse('POST is not used')
However, now the issue is that the Save As function should generate a new object for XMLGraph and Title which works fine, but once they click the save function it will delete the previous data for XMLGraph because of the following line in saveData
XMLGraph.objects.all().delete()
Save As in views.py:
#loggedin
def saveAs(request, user):
if request.method == "POST":
member = Member.objects.get(username=user)
graphTitle = request.POST['title']
title = Title.objects.create(title=graphTitle)
member.title.add(title)
xmlData = request.POST['xml']
xml = XMLGraph.objects.create(XMLGraph = xmlData, title=title)
member.XMLGraph.add(xml)
return render_to_response("fastcookapp/index.html", content_type="text/xml;")
return HttpResponse('POST is not used')
I am aware of .remove() being used instead of delete, but it doesn't seem to work properly as I can't remove the previous data that was added when the user presses save.

A for loop in forms.py fails to load data immediately after it's sent | Python Django

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'))

django upload files (models and forms)

I work on a group project with django. I have a problem with file upload. It is an web app to create, share forms with some additional options (graphs, charts,....). I should mention that i am new to django (total beginner)
1.models.py:
class Form(TimeStampedModel, TitleSlugDescriptionModel):
author = models.ForeignKey(User,
on_delete=models.CASCADE)
title = models.CharField(max_length=512)
is_final = models.BooleanField(default=False)
is_public = models.BooleanField(default=False)
is_result_public = models.BooleanField(default=False)
image = models.ImageField(upload_to="upload_location", null=True,
blank=True, width_field="width_field",
height_field="height_field")
height_field = models.IntegerField(default=0)
width_field = models.IntegerField(default=0)
file = models.FileField(upload_to="upload location", null=True,
blank=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('form-detail', kwargs={'slug': self.slug})
2. forms.py:
class DocumentUpload(forms.ModelForm):
class Meta:
model = Form
field = ["image", "file"]
3. Certainly, i made a migration, changed main settings (urls, MEDIA_ROOT etc)
4. views.py THIS IS MY PROBLEM
I try to modified existing "create_form(request)" function.
In any tutorials we use "form = form from forms.py", In my project we use "form = model from models.py". How should I modify this this function to complete this upload files.
def create_form(request):
if request.method == 'POST':
user = request.user
data = ParseRequest(request.POST)
parsed_form = data.form()
parsed_questions = data.questions()
form = Form(request.FILES, author=user,
title=parsed_form['title'],
is_final=parsed_form['is_final'],
is_public=parsed_form['is_public'],
is_result_public=parsed_form['is_result_public'],
description=parsed_form['description'])
form.save()
for d in parsed_questions:
question = Question(request.FILES, form=form, question=d['question'])
question.save()
for opt in d['options']:
option = Option(question=question, option=opt)
option.save()
return render(request, 'forms/form_form.html', {})
I would appreciate any help, thx
i needed to use a form from forms.py and add additional field manually.
Thx

Django model foreignkey queries

So i have this two models in django:
class Course(models.Model):
def get_image_path(self, filename):
return os.path.join('courses', str(self.slug), filename)
def __str__(self):
return self.name
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Course, self).save(*args, **kwargs)
name = models.CharField(max_length=255, verbose_name="Nombre")
description = models.CharField(max_length=255, verbose_name="Descripción")
price = models.DecimalField(max_digits=12,decimal_places=2, verbose_name="Precio")
slug = models.SlugField(blank=True, max_length=255)
icon_img = models.ImageField(upload_to=get_image_path, blank=True, null=True, verbose_name="Imagen")
background_color = ColorField(default="#026085")
class Meta:
verbose_name = "curso"
verbose_name_plural = "cursos"
class UserCourse(models.Model):
user = models.ForeignKey(User)
course = models.ForeignKey(Course)
So whenever a user "buys" a course, it is stored in UserCourse. I have a view where the system shows a list of all the courses the user has bought. This is the view code:
def user_course_list_view(request, username):
context_dict = {}
try:
user_courses = UserCourse.objects.filter(user=request.user).course_set
context_dict['courses'] = user_courses
context_dict['heading'] = "Mis cursos"
except:
context_dict['courses'] = None
context_dict['heading'] = "Mis cursos wey"
return render(request, 'courses/course_list.html', context=context_dict)
I dont know where is the error and I cant seem to catch the exception (im using django with docker)
tl;dr
Something like this should work.
usercourse_objects = UserCourse.objects.filter(user=request.user).select_related('course')
user_courses = [x.course for x in usercourse_objects]
Explanation
There are multiple ways to do this, but one way would be to first get all the UserCourse objects for the current user:
usercourse_objects = UserCourse.objects.filter(user=request.user)
Then, for each UserCourse object, get the related Course:
user_courses = [x.course for x in usercourse_objects]
Now, the second line causes N database queries (one for each time we follow the course foreign key relation. To prevent this, the first line can be changed to:
usercourse_objects = UserCourse.objects.filter(user=request.user).select_related('course')
This pre-populates the course attribute of the UserCourse objects. More info about select_related() can be found here.

Django Admin doesn't show entries

If I create a new entry for one particular model it doesn't show up in the django admin.
The Agency Model is causing the trouble.
# catalog.models
class Content(models.Model):
class Meta:
abstract = True
BUNDESLAND_CHOICES = (
('bw', 'Baden-Württemberg'),
('by', 'Bayern'),
('be', 'Berlin'),
('bb', 'Brandenburg'),
('hb', 'Bremen'),
('hh', 'Hamburg'),
('he', 'Hessen'),
('mv', 'Mecklenburg-Vorpommern'),
('ni', 'Niedersachsen'),
('nw', 'Nordrhein-Westfalen'),
('rp', 'Rheinland-Pfalz'),
('sl', 'Saarland'),
('sn', 'Sachsen'),
('st', 'Sachsen-Anhalt'),
('sh', 'Schleswig-Holstein'),
('th', 'Thüringen'),
)
name = models.CharField(max_length=255, verbose_name='Agentur')
address = models.CharField(max_length=255, verbose_name='Straße')
state = models.CharField(max_length=2, choices=BUNDESLAND_CHOICES, verbose_name='Bundesland')
city = models.CharField(max_length=255, verbose_name='Stadt')
zip = models.CharField(max_length=10, verbose_name='PLZ')
phone = models.CharField(max_length=40, blank=True, verbose_name='Telefonnr.')
fax = models.CharField(max_length=40, blank=True, verbose_name='Fax')
email = models.EmailField(verbose_name='E-Mail', help_text='Offizielle E-Mail')
url = models.URLField(verbose_name='URL')
owner = models.CharField(max_length=255, verbose_name='Besitzer')
description = models.TextField(verbose_name='Beschreibung')
category = models.ManyToManyField(Category, verbose_name='Kategorie')
user = models.ForeignKey(User, verbose_name='Benutzer', null=True, blank=True)
slug = models.SlugField(max_length=80, blank=True)
identity = models.CharField(max_length=64, unique=True, blank=True)
identity_used = models.BooleanField(default=False)
show = models.BooleanField(default=False, verbose_name='Anzeigen')
tp = models.DateTimeField(auto_now_add=True)
# agency.models
class AgencyActiveManager(models.Manager):
def get_query_set(self):
return super(AgencyActiveManager,self).get_query_set().filter(show=True)
class Agency(Content):
clients = models.TextField(verbose_name='Klienten')
active = AgencyActiveManager()
objects = models.Manager()
def __unicode__(self):
return self.name
def save(self, **kwargs):
if not self.identity:
self.identity = hashlib.sha256('%s:%s' %(get_word(),datetime.datetime.now())).hexdigest()
if not self.slug:
self.slug = slugify(self.name, instance=self)
super(Agency, self).save(**kwargs)
# agency.admin
from django.contrib import admin
from agency.models import Agency
admin.site.register(Agency)
I created a new Agency entry in the admin and saved it.
Querying via the python shell shows that the save worked
In [15]: Agency.objects.all()
Out[15]: [<Agency: Argentur>]
The admin page says:
'0 agencys'
If I try manually calling the url /admin/agency/agency/1/ I get a 404 saying that there is no agency object with a primarykey 1
Page not found (404)
Request Method: GET
Request URL: http://localhost:8000/admin/agency/agency/1/
Das agency-Objekt mit dem Primärschlüssel u'1' ist nicht vorhanden.
You're seeing this error because you have DEBUG = True in your Django settings file. Change that to False, and Django will display a standard 404 page.
But pythons shell says:
In [16]: Agency.objects.all()[0].pk
Out[16]: 1
Am I missing something extremely obvious?
My guess would be that it has something todo with the abstract model but I can't figure out what.
The first manager listed in the model class definition is the one that is used for the admin site and a number of other operations.
There have been a number of bugs in Django related to using a manager that does not return all instances as the default manager. IMHO, you are best to use a standard manager as the default, and add any more restrictive ones afterwards.
In fact, I no longer write models that use more than one manager. I would write
class AgencyManger(models.Manager):
def active(self):
return self.filter(show=True)
and use this as Agency.objects, so a root QuerySet for active objects is Agency.objects.active() rather than Agency.active.all(). This means .objects. will always have the same well-known behaviour. It's also easier to spot and understand in code.

Categories

Resources