Ive been trying to make this for two days now. I have created website that is capable of uploading one image file, but i would like to be able to upload more of them, that are connected to the same main model.
This is what i have for one picture upload:
forms.py:
from django import forms
from .models import Exam
class ExamForm(forms.ModelForm):
class Meta:
model = Exam
fields = ['exam_number', 'exam_file']
widgets = {
'exam_number': forms.NumberInput(
attrs={'id': 'exam_number', 'required': True,})
}
Models.py:
from django.db import models
from django.contrib.auth.models import User
from django.template.defaultfilters import slugify
from datetime import datetime
from django.core.validators import MaxValueValidator, MinValueValidator
class Exam(models.Model):
exam_number = models.PositiveIntegerField(validators=[MaxValueValidator(6),MinValueValidator(1)])
exam_path = models.CharField(max_length=255)
exam_file = models.ImageField() #i want to be able to upload more of these
exam_date = models.DateTimeField(auto_now_add=True)
exam_user = models.ForeignKey(User, null=True)
def __str__(self):
return self.exam_path
def __int__(self):
return self.exam_number
views.py:
def create_exam(request, letnik_id, classes_id, subject_id):
response_data = {}
if subject_id in SUBJECTS:
path = letnik_id + '/' + classes_id + '/' + subject_id
form = ExamForm(request.POST or None, request.FILES or None)
if form.is_valid():
exam = form.save(commit=False)
exam.exam_user = request.user
exam.exam_path = path
exam.exam_file = request.FILES['exam_file']
file_type = exam.exam_file.url.split('.')[-1]
file_type = file_type.lower()
if file_type not in IMAGE_FILE_TYPES:
context = {
'error_message': 'error',
}
return Http404("Napaka")
if Exam.objects.filter(exam_path=path, exam_number=exam.exam_number):
context = {
'form': form,
'error_message': 'error',
}
return render(request, 'tests.html', context)
exam.save()
return redirect('subject_id', letnik_id=letnik_id, classes_id=classes_id, subject_id=subject_id)
context = {
"form": form
}
raise Http404("error")
raise Http404("error")
ive heard that it would be best to make separated model for files, but i dont know how to make views that would connect to parent(exam) model.
Help is appreciated!
You need to create a separate model that would look something like this
class ExamFile(models.Model):
file = models.ImageField()
exam = models.ForeignKey(Exam, null=False)
Then in your view, instead of adding the exam_file to the exam, you will instead use it to create this new model. This will look something like this
from .models import Exam, ExamFile
...
exam_file = ExamFile.objects.create(
file = request.FILES['exam_file'],
exam=exam
)
For more information on fixing up the forms, you can check out the docs found here
Related
All other data is saved ideally but as shown below, the user id part shows as a pull down bar and a null value which should be a signed-in username.
What's wrong with my code?
The database page
Here's my code.
views.py
from .models import Markers
from .forms import AddMarkersInfo
from django.http import HttpResponse
def addinfo(request):
if request.method == 'POST':
mks = AddMarkersInfo(request.POST)
if mks.is_valid():
submit = mks.save(commit=False)
submit.user = request.user
submit.save()
name = mks.cleaned_data['name']
address = mks.cleaned_data['address']
description = mks.cleaned_data['description']
type = mks.cleaned_data['type']
lat = mks.cleaned_data['lat']
lng = mks.cleaned_data['lng']
Markers.objects.get_or_create(name=name, address=address, description=description, type=type, lat=lat, lng=lng)
return render(request, 'home.html', {'mks': mks })
else:
mks = AddMarkersInfo()
return render(request, 'home.html', {'mks': mks})
models.py
from django.db import models
from django.contrib.auth.models import User
from django.conf import settings
from django.contrib.auth import get_user_model
def get_sentinel_user():
return get_user_model().objects.get_or_create(username='deleted')[0]
class Markers(models.Model):
User = settings.AUTH_USER_MODEL
use_id= models.ForeignKey(User, null=True, on_delete=models.SET(get_sentinel_user),)
name = models.CharField(max_length=60,default = 'name')
address = models.CharField(max_length=100,default = 'address')
description = models.CharField(max_length=150, default='description')
types = (
('m', 'museum'),
('s', 'school'),
('r', 'restaurant'),
('o', 'other'),
)
type = models.CharField(max_length=60, choices=types, default='museum')
lat = models.IntegerField()
lng = models.IntegerField()
forms.py
from django import forms
from maps.models import Markers
class AddMarkersInfo(forms.ModelForm):
class Meta:
model = Markers
fields = ['name','address','description', 'type','lat','lng',]
Well, first of all, you should remove the lines from django.contrib.auth.models import User and User = settings.AUTH_USER_MODEL in models.py if you are going to use settings.AUTH_USER_MODEL. You should use only one of the two.
And you can change your field to:
use_id= models.ForeignKey(settings.AUTH_USER_MODEL, ...
Secondly, it seems like you are duplicating the creation. The lines
submit = mks.save(commit=False)
submit.user = request.user
submit.save()
already create an Markers instance, so there is no need to call Markers.objects.get_or_create(... after that.
And, according to you models, the field should be submit.use_id instead of submit.user.
Now, if I understand your question correctly you want to make the use_id field read-only in your form/template.
I don't know why that field is even showing up in your form, since it is not listed in your forms Meta.fields.
You could try something like setting the widget attribute readonly:
class AddMarkersInfo(forms.ModelForm):
class Meta:
model = Markers
fields = ['use_id', 'name', 'address', 'description', 'type', 'lat', 'lng']
widgets = {
'use_id': forms.Textarea(attrs={'readonly': 'readonly'}),
}
When I run this, I get JSON file but the foreign key (contact numbers) are not included, I want to display one contact name/address/email with multiple contact numbers.
models.py
from django.db import models
class PhoneBook(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=100, default='address')
email = models.CharField(max_length=50, default='email')
note = models.CharField(max_length=100, default='note')
def __str__(self):
return self.name
class ContactNumber(models.Model):
number = models.ForeignKey(PhoneBook, related_name="contact_numbers")
contact_number= models.CharField(max_length=30)
def __str__(self):
return self.contact_number
views.py
from django.shortcuts import render
from .models import PhoneBook,ContactNumber
from django.http import JsonResponse
from django.views import View
class PhoneBookList(View):
def get(self,request):
phonebooklist=list(PhoneBook.objects.values())
return JsonResponse(phonebooklist,safe=False)
admin.py
from django.contrib import admin
from .models import PhoneBook,ContactNumber
class ContactNumberInline(admin.StackedInline):
model = ContactNumber
class PhoneBookAdmin(admin.ModelAdmin):
inlines =[
ContactNumberInline,
]
admin.site.register(PhoneBook)
admin.site.register(ContactNumber)
RESULT:
enter image description here
I might be able to answer with this approach.
class PhoneBook(models.Model):
....
def to_json(self):
contact_numbers = [c.contact_number
for c in self.contact_numbers.all()]
return {
'name': self.name,
'email': self.email,
'address': self.address,
'note': self.note,
'contact_numbers': contact_numbers
}
In your view.
class PhoneBookList(View):
def get(self,request):
phonebooklist = PhoneBook.objects.all()
serialized_data = [pb.to_json() for pb in phonebooklist]
return JsonResponse(serialized_data, safe=False)
A bit dirty solution though
I'm having problem in saving selected choices in the same row of data table for each participant).
I have 2 forms. The first form is for some data and a multiple-choice question. The second form is another multiple-choice question. It also means I have 2 pages, after submit answers for page 1, it will redirect to page 2 for question 2.
When I try to be a participant and choose answers, the selected choices are saved in different data table. Pictures and code are displayed below.
forms.py
from django import forms
from .models import Survey
class SurveyForm(forms.ModelForm):
BAT='Batman'
SUPER='Superman'
IRON='Ironman'
WHATMOVIE1 = [
(BAT, 'Batman'),
(SUPER, 'Superman'),
(IRON, 'Ironman'),
]
movie_1 = forms.ChoiceField(choices=WHATMOVIE1, widget=forms.RadioSelect())
class Meta:
model = Survey
fields = ["location", "age",
"marital_status", "education", 'movie_1']
class SurForm(forms.ModelForm):
APP='Apple'
BAN='Banana'
LEM='Lemon'
WHATMOVIE2 = [
(APP, 'Apple'),
(BAN, 'Banana'),
(LEM, 'Lemon'),
]
movie_2 = forms.ChoiceField(choices=WHATMOVIE2, widget=forms.RadioSelect())
class Meta:
model = Survey
fields = [ 'movie_2']
views.py
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from .forms import SurveyForm, SurForm
def homepage(request):
if request.method == 'POST':
title = "Questionnaire"
form = SurveyForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
return HttpResponseRedirect(reverse('nextpage'))
else:
form = SurveyForm()
return render(request, "homepage.html", {"form": form})
def nextpage(request):
title = "Next page"
form = SurForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
context = {
"form": form,
}
return render(request, "nextpage.html", context)
admin.py
from django.contrib import admin
from .forms import SurveyForm, SurForm
from .models import Survey, Sur
class SurAdmin(admin.ModelAdmin):
form = SurForm
class SurveyAdmin(admin.ModelAdmin):
list_display = ["location", "age",
"marital_status", "education",
"movie_1"]
form = SurveyForm
admin.site.register(Survey, SurveyAdmin)
admin.site.register(Sur, SurAdmin)
What should I do to save all selected answers in the same row for each participant?
You are using two different models, that is why they are getting separated. You need to create a relation between them, using a OneToOneField can solve the problem. Something like this:
from django.db import models
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
def __str__(self): # __unicode__ on Python 2
return "%s the place" % self.name
class Restaurant(models.Model):
place = models.OneToOneField(Place, primary_key=True)
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
def __str__(self): # __unicode__ on Python 2
return "%s the restaurant" % self.place.name
Optionally, you can just combine the two models.
I am working on form models and get this error:
global name 'AdForm' is not defined
In my view I have:
from django.template import RequestContext, loader
from django.http import HttpResponse
from django.shortcuts import redirect
from django.contrib.auth.decorators import login_required
from django import forms
#login_required
def create(request):
if request.POST:
ad = AdForm(request.POST)
if ad.is_valid():
test = 'valid'
else:
test = 'invalid'
else:
test = 'none'
template = loader.get_template('ads/create.html')
context = RequestContext(request, {
'test': test
})
return HttpResponse(template.render(context))
However it is not picking up my model. My model in my view is:
from django.db import models
from django.forms import ModelForm
TYPE_CHOICES = (
'Image',
'Code',
)
SIZE_CHOICES = (
'Leaderboard',
'Banner',
'Skyscraper',
'Square',
)
class Ad(models.Model):
title = models.CharField(max_length=40)
type = models.CharField(max_length=7)
size = models.CharField(max_length=16)
clicks = models.IntegerField()
media = models.ImageField(upload_to='ads')
link = models.URLField(null=True)
created = models.DateTimeField(auto_now_add=True)
expires = models.DateTimeField(null=True)
def __unicode__(self):
return self.name
class AdForm(ModelForm):
class Meta:
model = Ad
Does anyone know why it is not picking up the form model?
Thanks from a noob.
At the top of your view, you need:
from .models import AdForm
Also, forms usually go in forms.py, not with the models.
I create a modelForm with instance to existing model (Book). I am not able to update the Books record. Adding a new record is fine but when I attempt to update, it appears to be unable to find the publisher (which is a foreign key). Error is "No Publisher matches the given query."
models.py
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
def __unicode__(self):
return self.name
class Meta:
ordering = ["name"]
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField(blank=True, verbose_name='e-mail')
objects = models.Manager()
sel_objects=AuthorManager()
def __unicode__(self):
return self.first_name+' '+ self.last_name
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField(blank=True, null=True)
num_pages = models.IntegerField(blank=True, null=True)
class BookForm(ModelForm):
class Meta:
model = Book
views.py
def authorcontactupd(request,id):
if request.method == 'POST':
a=Author.objects.get(pk=int(id))
form = AuthorForm(request.POST, instance=a)
if form.is_valid():
form.save()
return HttpResponseRedirect('/contact/created')
else:
a=Author.objects.get(pk=int(id))
form = AuthorForm(instance=a)
return render_to_response('author_form.html', {'form': form})
error msg
Page not found (404)
Request Method: POST
Request URL: http://127.0.0.1:8000/books/bookupd/
No Publisher matches the given query.
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.
urls.py
from django.conf.urls.defaults import *
from django.views.generic.simple import direct_to_template
from mysite10.books.views import about_pages, books_by_publisher, authorcontact,bookcontact, booklisting, authorcontactupd
from django.views.generic import list_detail
from mysite10.books.models import Publisher, Book
from django.contrib import admin
admin.autodiscover()
def get_books():
return Book.objects.all()
publisher_info = {
'queryset': Publisher.objects.all(),
'template_name':'books/publisher_publisher_list_page.html',
'template_object_name': 'publisher',
'extra_context': {'book_list': Book.objects.all},
}
book_info = {
'queryset': Book.objects.order_by('-publication_date'),
'template_name':'books/publisher_publisher_list_page.html',
'template_object_name': 'book',
'extra_context': {'publisher_list': Publisher.objects.all},
}
oreilly_books = {
'queryset': Book.objects.filter(publisher__name="O'Reilly"),
'template_name':'books/publisher_publisher_list_page.html',
'template_object_name': 'book',
'extra_context': {'publisher_list': Publisher.objects.all},
}
urlpatterns = patterns('',
(r'^admin/(.*)', admin.site.root),
(r'^polls/', include('mysite10.polls.urls')),
(r'^search-form/$', 'mysite10.views.search_form'),
(r'^search/$', 'mysite10.views.search'),
(r'^contact/$', 'mysite10.contact.views.contact'),
(r'^contact/thanks2/(\d+)$', 'mysite10.contact.views.thanks2'),
(r'^contact/thanks/$', 'mysite10.contact.views.thanks'),
(r'^publishers/$', list_detail.object_list, publisher_info),
(r'^books/$', list_detail.object_list, book_info),
(r'^books/oreilly/$', list_detail.object_list, oreilly_books),
(r'^books/(\w+)/$', books_by_publisher),
(r'^author/$', authorcontact),
(r'^authorupd/(\d+)/$', authorcontactupd),
(r'^contact/created/$', 'mysite10.books.views.created'),
(r'^bookform/$', bookcontact),
(r'^contact/bookscreated/$', 'mysite10.books.views.books_created'),
(r'^booklist/$', 'mysite10.books.views.booklisting'),
(r'^books/bookupd/(\d+)$', 'mysite10.books.views.book_upd'),
)
-------------------------------------------------
I finally got it working with below codes.
error in urls.py because of missing forward slash before $.
Amended to (r'^books/bookupd/(\d+)/$'
views.py
def book_upd(request,id):
if request.method == 'POST':
a=Book.objects.get(pk=int(id))
form = BookForm(request.POST, instance=a)
if form.is_valid():
form.save()
return HttpResponseRedirect('/contact/bookscreated')
else:
a=Book.objects.get(pk=int(id))
form = BookForm(instance=a)
return render_to_response('book_form.html', {'form': form})
urls.py
(r'^books/bookupd/(\d+)/$', 'mysite10.books.views.book_upd'),
There's some missing information like what you have in your urls.py. Can you post it as well? Did you check in the database that the record was actually not updated? (the error might be a result of processing the redirect)
Your edit is not sufficient:
- did you check the databse to see if the record is updated?
- Please paste the entire urls.py as for example it is interesting to see what /contact/created is mapped to in case it did succeed, or whether you have some publisher.get() methods in it
In addition the traceback can also provide lots of useful information as to the source of the problem.
did you check if the object is updated in the database even though you get the error?
Can you try removing the "oreilly_books" section (or at least the queryset part) and try doing the same without it?