What's the best method of saving an existing record as a new record when in a specific view?
I cannot use default values in a CreateView because the defaults will change depending on the type of record the user is creating.
models.py
class videos(models.Model):
title = models.CharField(max_length=250)
fk_type = models.ForeignKey('mediaTypes',on_delete=models.CASCADE)
b_template = models.BooleanField(default=False)
class mediaTypes(models.Model):
name = models.CharField(max_length=250)
e.g.
1 - Football game - 4 - TRUE
2 - Superbowl X highlights - 4 - FALSE
3 - Superbowl XX highlights - 4 - FALSE
4 - Home movies - 2 - TRUE
5 - Finding Holy Gail under house - 2 - FALSE
forms.py
from django import forms
from django.forms import ModelForm
from .models import (videos)
class create_football(ModelForm):
class Meta:
model = videos
fields = '__all__'
views.py
from django.shortcuts import render, get_object_or_404, redirect
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.urls import reverse
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.models import User, AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.contrib.auth.decorators import login_required
from django.db.models import Q # filter using operators '&' or '|'.
from django.utils import timezone
from users.models import Profile
from django.forms import ModelForm
from django.http import HttpResponseRedirect
from .models import (videos)
from .forms import (create_football)
class templates(LoginRequiredMixin, ListView):
model = videos
template_name = 'videos/templates.html'
context_object_name = 'video'
def get_queryset(self):
profile = get_object_or_404(Profile, user=self.request.user)
queryset = videos.objects.filter(Q(fk_type="4")
return queryset
class create_football(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = videos
form_class = create_football
template_name = 'videos/create_football.html'
def form_valid(self, form):
messages.success(self.request, 'form is valid')
form.instance.user = self.request.user
form.save()
To create a new football video, the user selects the record titled 'football game' from the templates view - which opens an update view. This dummy template record has the fk_type and other fields automatically set to the appropriate value.
I need this view to save the changes the user will make, such as to the title, as a new record.
Related
I've been attempting to construct a multi-step form using the Django session wizard for hours, but I keep getting the error, AttributeError: 'function' object has no property 'as_view'. I'm not sure why this mistake occurred. Any ideas?
views
from django.shortcuts import render
from formtools.wizard.views import SessionWizardView
from .forms import WithdrawForm1, WithdrawForm2
class WithdrawWizard(SessionWizardView):
template_name = 'withdraw.html'
form_list = [WithdrawForm1, WithdrawForm2]
def done(self, form_list, **kwargs):
form_data = [form.cleaned_data for form in form_list]
return render(self.request, 'done.html', {'data': form_data})
forms
from django import forms
from .models import Investment, Withdraw
from .models import WithdrawStepOne, WithdrawStepTwo
class WithdrawForm1(forms.ModelForm):
class Meta:
model = WithdrawStepOne
fields = ['investment_id',]
class WithdrawForm2(forms.ModelForm):
class Meta:
model = WithdrawStepTwo
fields = [
'proof_of_address',
'user_pic'
]
urls
from django.urls import path
from .forms import WithdrawForm1, WithdrawForm2
from . import views
urlpatterns = [
path('withdraw/', views.WithdrawWizard.as_view(), name='withdraw'),
]
You used #login_required decorator on WithdrawWizard class, but the decorator works only for function based views.
Use LoginRequiredMixin for class based views.
Note: I am a django/python beginner
I currently have a User class in models.py that allows a user to upload an image to my app. This is supported by a form and template that allow the upload. This part is working fine. The issue is that I am receiving the image in the filefield within the model, but i need to get this image into my EnhanceImage.py file. Once there, I can process it with the code in this script to create an enhanced version with Pillow.
How should I set this up differently than what I am doing now? The goal in my mind is to get the image variable from the User class into the EnhanceImage.py file to be used for enhancement. I want to get it into the UserUploadedImage variable in the EnhanceImage.py file
I've tried just about every solution i can find online to pass the variable to the new file.
Models.py
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from stdimage.models import StdImageField
class User(models.Model):
name = models.CharField(max_length=100)
content = models.CharField(max_length=50, default='something')
email = models.EmailField(blank=True)
password = models.CharField(max_length=50)
image = StdImageField(upload_to='images/', variations={'thumbnail': {'width': 640, 'height': 480}}, default='default.jpg')
def __str__(self):
return self.name
ImageEnhance.py
The goal of this file is to take the UserUploadedImage and overlay content using pillow.
from PIL import Image, ImageEnhance, ImageFont, ImageDraw
UserUploadedImage = I need the user uploaded image here!
foreground = Image.open("path/to/Image_to_overlay.jpg")
draw = ImageDraw.Draw(UserUploadedImage)
draw.rectangle([(-11, 420), (640, 515)], fill=(255,255,255), outline=(0,0,0))
UserUploadedImage.paste(foreground, (300, 385), foreground)
...
#more code below that isn't important for my question
Forms.py
from django.forms import ModelForm
from django import forms
from .models import User
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ['name', 'email', 'content', 'image']
Views.py
from django.shortcuts import render, redirect
from django.http import HttpResponse
from .models import User
from django.views.generic import ListView, CreateView # new
from django.urls import reverse_lazy #new
from .forms import UserForm # new
def home(request):
context = {
'users': User.objects.all()
}
return render(request, 'main/home.html', context)
class CreateUploadView(CreateView): # new
model = User
form_class = UserForm
template_name = 'main/photoupload.html'
success_url = reverse_lazy('home')
I have a users app in a Django project (version 2.1 and python 3.6). After an user signup (both front end and when added in the admin dashboard ideally), I'd like to insert data in one other table. I know how to insert data, but I didn't find out how to do it right after a successfull signup.
Ideal answer would just show me how to do something like print('hello') right after an user created his account.
# users/admin.py
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from .forms import CustomUserCreationForm, CustomUserChangeForm
from .models import CustomUser
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
form = CustomUserChangeForm
model = CustomUser
list_display = ['email', 'username',]
admin.site.register(CustomUser, CustomUserAdmin)
# users/forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import CustomUser
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm):
model = CustomUser
fields = ('username', 'email')
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = CustomUser
fields = ('username', 'email')
# users/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
# add additional fields in here
credit = models.IntegerField(default=200) # editable=False
def __str__(self):
return self.email
# users/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('signup/', views.SignUp.as_view(), name='signup'),
]
# users/views.py
from django.urls import reverse_lazy
from django.views import generic
from .forms import CustomUserCreationForm
class SignUp(generic.CreateView):
form_class = CustomUserCreationForm
success_url = reverse_lazy('login')
template_name = 'signup.html'
Use a post-save signal
https://docs.djangoproject.com/en/2.1/ref/signals/
from django.db.models.signals import post_save
from django.dispatch import receiver
#receiver(post_save, sender=User)
def say_hello(sender, instance, **kwargs):
if instate._state.adding:
print('hello')
Signal is better than a method on the view because the User may be created some way other than through the view e.g , via the shell, a management command, a migration, a different view, etc.
Note the _state is not "private" so don't feel bad about using it, it's just named that way to avoid clashing with field names.
Check _state instead of more common checking instance.pk because instance.pk is always present when primary key is a natural key rather than AutoField
I think the best approach would be overriding save method of CustomUser model. For example:
class CustomUser(AbstructUser):
def save(self, *args, **kwargs):
user = super(CustomUser, self).save(*args, **kwargs)
print("Hello World")
return user
Check here in Django documentation for more details: https://docs.djangoproject.com/en/2.1/topics/db/models/#overriding-predefined-model-methods.
I seem to be having a TypeError problem on my program using Django.
Views.py
from __future__ import unicode_literals
from django.shortcuts import render
from .models import Anteproyecto
from .forms import formulario_anteproyecto
from django.views.generic import CreateView
from django.core.urlresolvers import reverse, reverse_lazy
from django.contrib.messages.views import SuccessMessageMixin
class CrearAnteproyecto(SuccessMessageMixin, CreateView):
model = Anteproyecto
form_class = formulario_anteproyecto
template_name = "crear_anteproyectos.html"
success_url = reverse_lazy('crear_anteproyecto')
success_message = "El anteproyecto ha sido creado"
def form_valid(self, form):
self.object = form.save()
Forms. py
from django import forms
from .models import Anteproyecto
class formulario_anteproyecto:
class Meta:
model = Anteproyecto
fields = ['titulo', 'resumen','estado','palabras_claves']
Models.py
from __future__ import unicode_literals
from django.db import models
from taggit.managers import TaggableManager
from Actividades.models import Actividades
ESTADOS = (('Activo', 'Activo'), ('Inactivo', 'Inactivo'))
class Anteproyecto(models.Model):
titulo = models.CharField(max_length=100, verbose_name='TÃtulo')
estado = models.CharField(max_length=8, verbose_name="Estado", choices=ESTADOS, default='Activo')
resumen = models.CharField(max_length=500, verbose_name="Resumen")
claves = TaggableManager(verbose_name = "Palabras claves")
actividad = models.ForeignKey(Actividades, on_delete=models.CASCADE)
class Meta :
verbose_name = 'Anteproyecto'
verbose_name_plural = 'Anteproyectos'
def __str__(self):
return self.titulo
Importing the app "Actividades" to be used as a reference in models. Using as well Django-taggit to use a field that can work as tags, still not implemented due to TypeError. Html is a bootstrap template which prints the form as a paragraph. There are other creates in different views that use the same coding as this however this one is giving me the error.
Your formulario_anteproyecto does not inherit from anything. It needs to inherit from forms.ModelForm.
This is my original thought on how to accomplish this:
products = Product.objects.all()
for product in products:
if product in cart:
products = Product.objects.exclude(product)
My two questions are:
1.) Does this work/ make sense?
2.) Which .py file would I put it in?
views.py
from django.shortcuts import render
from django.shortcuts import HttpResponseRedirect
from django.core.urlresolvers import reverse
from .models import Dropoff, DropoffItem
from products.models import Product
from .forms import AddDropoffItemForm
from django.contrib.auth.models import User
from django.contrib import messages
from django.contrib.auth.decorators import login_required
def add_item_dropoff_order(request):
request.session.set_expiry(120000)
try:
user = request.user
the_id = request.session['dropoff_id']
dropoff = Dropoff.objects.get(id=the_id)
except:
user = request.user
new_dropoff_order = Dropoff(user=user)
new_dropoff_order.save()
request.session['dropoff_id'] = new_dropoff_order.id
the_id = new_dropoff_order.id
dropoff = Dropoff.objects.get(id=the_id)
try:
product = Product.objects.get(sku=sku)
except Product.DoesNotExist:
pass
except:
pass
form = AddDropoffItemForm(request.POST or None)
if request.method == "POST":
product_sku = str(request.POST['product'])
dropoff_item = DropoffItem.objects.create(dropoff=dropoff, product_id=product_sku)
dropoff_item.save()
return HttpResponseRedirect('%s'%(reverse('add_item_dropoff_order')))
context = {
"dropoff": dropoff,
"form": form,
}
return render(request, 'dropoffs/add_item_dropoff_order.html', context)
forms.py
from django import forms
from .models import Dropoff, DropoffItem
from products.models import Product
class AddDropoffItemForm(forms.ModelForm):
product = forms.ModelChoiceField(queryset=Product.objects.all(), widget=forms.Select(attrs={'class':'form-control'}))
class Meta:
model = DropoffItem
fields = ["product"]
So basically, once dropoff_item.save() occurs, I want to remove that product from the queryset being called in the forms.py file.
Is it possible to redefine the queryset in the views and then call it again in the forms.py?
No, not really :) I would approach this like:
products = Product.objects.exclude(id__in=cart.product_ids)
Without seeing your application logic, it's impossible to tell you where to put this code, but since you've tagged django views, I'm assuming you want it in a view.