I´m doing a simple user-business application, where a user has one or many business. The problem is that my create business forms is not saving its data to the database. The user has all the permissions and is active, and I can save data from the create user form with no problem. What is wrong?
View.py:
class crear_negocio(LoginRequiredMixin, FormView):
template_name = "tienda/crear_negocio.html"
form_class= Negocio_Form
success_url = reverse_lazy('tienda_app:crear_negocio')
login_url = reverse_lazy('register_app:logIn')
form.py:
class Negocio_Form(forms.ModelForm):
class Meta:
model = Negocio_Model
fields = ("Nombre_Negocio","Administrador","Descipcion_Negocio",'Correo_Negocio','Telefono_Negocio','Direccion_Negocio')
Model.py:
class Negocio_Model(models.Model):
Nombre_Negocio = models.CharField(max_length=25)
Administrador = models.ForeignKey(Usuario_Model, on_delete=models.CASCADE)
Descipcion_Negocio = models.TextField(null=True, blank=True)
Correo_Negocio = models.EmailField()
Telefono_Negocio = models.CharField(max_length=13)
Direccion_Negocio = models.CharField(max_length=25)
def __str__(self):
return self.Nombre_Negocio+' '+self.Correo_Negocio+' '+self.Telefono_Negocio+' '+self.Direccion_Negocio
Database config:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'bdtg1',
'USER':'juan',
'PASSWORD':'juanjo123',
'HOST':'127.0.0.1',
'PORT':'3306'
}
}
A FormView does not .save() the form, thus it will indeed not create a record at the database. By default in case the form is successful, it redirects to the success URL, that's all. A typical use case of a FormView is for example to send an email instead of saving it to the database.
You can override the form_valid(…) method [Django-doc] to save the form, but it might be better to make use of a CreateView [Django-doc]:
from django.views.generic.edit import CreateView
class crear_negocio(LoginRequiredMixin, CreateView):
template_name = 'tienda/crear_negocio.html'
form_class= Negocio_Form
success_url = reverse_lazy('tienda_app:crear_negocio')
login_url = reverse_lazy('register_app:logIn')
Related
Currently I have a date picker in a django model form that works perfectly fine. However, I want to add an initial (default) value to it. Here is my current code :
class DatePickerInput(forms.DateInput):
input_type = 'date'
class PDFClassificationForm(forms.ModelForm):
class Meta:
model = Documents
fields = [
'id_documenttype',
'dateenvoi',,
'comment']
widgets = {
'dateenvoi' : DatePickerInput(),
}
I tried adding initial as a parameter to DatePickerInput() like so :
widgets = {
'dateenvoi' : DatePickerInput(initial= datetime.now().strftime('%d/%m/%y %H:%M:%S')),
}
However it was unsuccessful, any suggestions ?
Try this:
import datetime
class PDFClassificationForm(forms.ModelForm):
class Meta:
model = Documents
fields = [
'id_documenttype',
'dateenvoi',
'comment',
]
widgets = {
'dateenvoi' : DatePickerInput(widget=forms.TextInput(attrs={'value': datetime.now().strftime('%d/%m/%y %H:%M:%S')})),
}
try adding your desired initial value to the form in the view (views.py)
import datetime
from django.views.generic import TemplateView
from .forms import PDFClassificationForm
class YourView(TemplateView):
template_name = 'your_directory/your_template_name.html'
form_class = PDFClassificationForm
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
return render(request, self.template_name, {'form': form})
def get_context_data(self, *args, **kwargs):
context = super(YourView, self).get_context_data(*args, **kwargs)
request = self.request
context["form"] = PDFClassificationForm(request.POST or None, initial={ "dateenvoi": datetime.today)
return context
This is my first time using FastApi the python framework and i am trying to understand how to correctly setup my tables and logic to be able to make a post request that create an instance of the table that has the foreign key
models.py
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
first_name = Column(Text, nullable=False)
last_name = Column(Text, nullable=False)
class Post(Base):
__tablename__ = "posts"
id = Column(Integer, primary_key=True, index=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
schemas.py
class UserBase(BaseModel):
name: str
class Posts(BaseModel):
id: int
user_id: int
class Config:
orm_mode = True
class User(UserBase):
id: int
class Config:
orm_mode = True
repository.py
def create_post(db: Session, user_id: int, post: schemas.Post):
get_user_id = db.query(models.User).filter(models.User.id == user_id).first()
post = models.Post(
id=post.id,
user_id=get_user_id.id,
)
db.add(post)
db.commit()
db.refresh(post)
return post
endpoint
router = APIRouter()
#router.post("/posts.", response_model=Post)
async def create_post(user_id, post: Post, db):
return repository.create_post(db=db, user_id=user_id, post=post)
front end
try {
const url = "http://localhost:8000/posts";
const data = {"user_id": 2};
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
...
The user_id tried above in the front end exist in the database and the endpoint to create a user work fine but just the one to create a post that belong to a specific user do not work return a 422 (Unprocessable Entity)
Is there something that i am doing wrong?
Your endpoint currently requires 2 things: a user_id and data from a Post schema. (It also asks for db which I don't know how you manage your access to your db) (create_post(user_id, post: Post, db))
So your body must contain the values of Post, namely: id and user_id. At this point, we realize that you ask twice in your endpoint user_id . You can therefore delete your first user_id from your endpoint since it is included in your Post schema.
On the front-end, your data contains only one data: {"user_id": 2}. It is missing the value for id which is requested via your Post schema. So, since there is one piece of data missing, a 422 error is raised.
I have 2 User and EcoUser models with relation of 1 to 1 (I have reduced the fields of the tables for this example):
class User(AbstractUser):
picture_url = models.ImageField(upload_to='logos/', blank=True)
class EcoUser(models.Model):
user = models.OneToOneField(User, related_name='eco_user')
document = models.CharField(max_length=45, blank=True)
def __str__(self):
return str(self.user)
In which I use a NestedSerializer to be able to create and update the data of the two tables in a single post or put in this way I did the update since in the register I do not keep images and I have no problem with it:
This is the serializer:
class EcoUserSerializer(serializers.ModelSerializer):
user = UserSerializer(required=True)
class Meta:
model = EcoUser
fields = '__all__'
def update(self, instance, validated_data):
instance.document = validated_data.get('document', instance.document)
instance.save()
user_data = validated_data.pop('user')
user = instance.user
user.picture_url = user_data.get('picture_url', user.picture_url)
user.save()
return instance
and in my viewset:
class EcoUserViewSet(viewsets.ModelViewSet):
serializer_class = EcoUserSerializer
queryset = EcoUser.objects.all()
pagination_class = None
parser_classes = (MultiPartParser,)
#transaction.atomic
def update(self, request, *args, **kwargs):
with transaction.atomic():
try:
instance = self.get_object()
instance.id = kwargs.get('pk')
serializer = EcoUserSerializer(instance=instance, data=request.data)
print(serializer)
if serializer.is_valid(raise_exception=True):
self.perform_update(serializer)
return Response({"status": True, "results": "Datos actualizados correctamente"},
status=status.HTTP_201_CREATED)
except ValidationError as err:
return Response({"status": False, "error_description": err.detail}, status=status.HTTP_400_BAD_REQUEST)
This worked correctly until I added the ImageField field and it did not update my data and I got a 400 bad request error. This I send to him of the VUEJS by axios:
const bodyFormData = new FormData();
bodyFormData.append('user.picture_url', this.params.user.picture_url.name);
bodyFormData.append('document', this.params.document);
this.axios.put(`/users/${this.params.id}/`, bodyFormData, { headers: { 'Content-Type': 'multipart/form-data' } })
.then((response) => {
this.isSending = false;
this.$snackbar.open(response.data.results);
});
It's okay if in the apppend as field name I put user.picture_url? since it is inside the user object and then I already access the picture_url to be able to update it.
Probe of the postman and I realized the error: It was simply that the username field of the django table was mandatory:
const bodyFormData = new FormData();
bodyFormData.append('user.picture_url', this.params.user.picture_url.name);
bodyFormData.append('document', this.params.document);
bodyFormData.append('user.username', this.params.username);
and it worked wonders : D
I've just got a simple upload form:
def post(request):
if request.user.is_authenticated():
form_post = PostForm(request.POST or None, request.FILES or None)
if form_post.is_valid():
instance = form_post.save(commit=False)
instance.user = request.user
instance.save()
return HttpResponseRedirect('/home/')
else:
form_post = PostForm()
context = {
'form_post': form_post,
}
return render(request, 'post/post.html', context)
else:
return HttpResponseRedirect("/accounts/signup/")
which derives from here:
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = [
'title',
'image',
'user'
]
and here's the models:
class Post(models.Model):
user = models.ForeignKey(User, blank=True, null=True)
title = models.TextField(max_length=95)
image = models.FileField(null=True, blank=True)
When a user adds an image to the form, it fires this JS function:
$('input#id_image').on('change', function(e) {...}
which gives a preview of the image. This is the point where I want the image to be uploaded to my media folder directory (I'm using S3 storage). By default, the image is uploaded when the user submits the form, but I want it to be uploaded as soon as $('input#id_image').on('change' is triggered.
How would I go about this?
Just send your form as ajax request in your onChange handler:
$('input#id_image').on('change', function(e) {
$.ajax({
url: "your endpoint here",
type: "POST",
data: new FormData($(form#yourFormID)[0])
}).done(function(data) {
//on success code
}).fail(function(data, err) {
//on fail code
}).always(function() {
//whatever to be done no matter if success or error
});
}
I've gone through many tutorials in how to integrate ajax with django form but all were complicated. I have a Signup model with Signup form and a views like the following.
models.py
from django.db import models
class SignUp(models.Model):
name = models.CharField(max_length=120, blank=True, null=True)
email = models.EmailField()
def __unicode__(self):
return self.email
and forms.py
from django import forms
from .models import SignUp
class SignUpForm(forms.ModelForm):
class Meta:
model = SignUp
fields = ['name', 'email']
def clean_name(self):
name = self.cleaned_data.get('name')
return name
def clean_email(self):
email = self.cleaned_data.get('email')
try:
match = SignUp.objects.get(email=email)
except SignUp.DoesNotExist:
return email
raise forms.ValidationError('This email address is already subscribed.')
views.py
from django.shortcuts import render
from django.core.mail import send_mail
from django.conf import settings
from .forms import SignUpForm
def index(request):
form = SignUpForm(request.POST or None)
if form.is_valid():
name = form.clean_name()
email = form.clean_email()
instance = form.save()
subject = 'Bruke Church news'
from_email = settings.EMAIL_HOST_USER
to_email = [email]
contact_message = "%s:Thank you for signing up for our newsletter via %s. we'll be in touch" %(
name,
email)
send_mail (subject,
contact_message,
from_email,
to_email,
fail_silently=False)
context = {
"form": form
}
return render(request, "index.html",context)
and my html form looks like this
<form action="" method="POST">
{% csrf_token %}
{{form|crispy}}
<input type="submit" value="Sign up" class="btn btn-primary">
</form>
This code runs well but it loads the full page and I want to load only the form. After googling, I found a concept of Ajax but am really having problem in doing so. please help me Thank you
Example of Ajax Post
on button click submit
this method needs to run
put this in your HTML
function AddData(){
var name = $("#name").val();
var email = $("#email").val();
// You should extract each and every id from your form fields
var signupData = { name:name, csrfmiddlewaretoken: '{{ csrf_token }}',email:email};
$.ajax({
type: "POST",
url: "../../index/",
data: signupData,
success: function(data) {
alert("You Have Sucessfully Signed Up ");
},
statusCode: {
500: function() {
alert("You Have Already Signed Up ");
}
},
})
}
In your Views.py
def index(request):
if request.method == 'POST': # From Frontend we are getting the data in a POST method and we are checking if front end is giving POST Method or not
get_email = request.POST.get('email') # Taking The DATA from front end in form of POST to Django USER EMAIL ADDRESS
get_name = request.POST.get('name')# Taking The DATA from front end in form of POST to Django NAME
queryset_list = SignUp.objects.all().values_list("email",flat=True)# Performing a Django Query and getting all Signup Email Address
if get_email in queryset_list:
return HttpResponse(status=500)
else:
SignUp.objects.create(name=get_name,email=get_email)
return HttpResponse('')