NOT NULL constraint failed: accounts_personalcolor.user_id - reactjs

I am new to Django and have trouble making django-rest-framework API for post, inheriting APIView. I'm using a serializer, that inherits djangos ModelSerializer. I face NOT NULL constraint failed: accounts_personalcolor.user_id error whenever I try saving the serializer or model object.
color.js posts image using Django rest framework as follows.
function PersonalColorScreen({navigation,route}) {
const {image} = route.params;
console.log('uri is', image.uri);
const [userToken, setUserToken] = React.useState(route.params?.userToken);
const requestHeaders = {
headers: {
"Content-Type": "multipart/form-data"
}
}
// helper function: generate a new file from base64 String
//convert base64 image data to file object to pass it onto imagefield of serializer.
//otherwise, serializer outputs 500 Internal server error code
const dataURLtoFile = (dataurl, filename) => {
const arr = dataurl.split(',')
const mime = arr[0].match(/:(.*?);/)[1]
const bstr = atob(arr[1])
let n = bstr.length
const u8arr = new Uint8Array(n)
while (n) {
u8arr[n - 1] = bstr.charCodeAt(n - 1)
n -= 1 // to make eslint happy
}
return new File([u8arr], filename, { type: mime })
}
//random number between 0-9
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
// generate file from base64 string
const file = dataURLtoFile(image.uri, `${getRandomInt(10)}.png`)
const formData= new FormData();
formData.append('img',file,file.name);
console.log(file.name);
//axios post request to send data
// axios.post('http://localhost:8000/accounts/personalcolor/', formData,requestHeaders)
//multipartparser
axios.post('http://localhost:8000/accounts/personalcolor/', formData, requestHeaders)
.then(res => {
console.log(res);
if (res.data === 'upload another image') {
setimageError('upload another image');
} else {
// signUp(userToken);
let color;
switch (res.data){
case ('spring'):
color = 'spring';
break;
case ('summer'):
color = 'summer';
break;
case ('fall'):
color = 'fall';
break;
case ('winter'):
color = 'winter';
break;
}
}
})
.catch(err => {
console.error(err.response.data)
})
view.py handles the image posted. I tried #1 but it did not work. So I tried #2, or #3 instead and they return the same error saying NOT NULL constraint failed: accounts_personalcolor.user_id. I thought saving the serializer or model object creates id(Autofield)automatically and I don't understand why I face this error.
views.py
#api_view(['POST'])
def personalcolor(request):
# 1
image=request.FILES['img']
personal_color=Personalcolor()
personal_color.img=image
personal_color.save()
# 2
image=request.FILES['img']
personal_color=Personalcolor.objects.create(img=image)
personal_color.save()
# 3
serializer = ColorSerializer(data=request.data)
# validation of input data
if serializer.is_valid():
serializer.save()
else:
return Response(serializer.errors, status = status.HTTP_400_BAD_REQUEST)
model.py
class Personalcolor(models.Model):
objects = models.Manager()
img = models.ImageField('personal_img',upload_to="personalcolor/", blank=True)
serializer.py
class ColorSerializer(serializers.ModelSerializer):
class Meta:
model = Personalcolor
fields = ['img']
As mentioned above, executing the code returns django.db.utils.IntegrityError: NOT NULL constraint failed: accounts_personalcolor.user_id. Any help would be greatly appreciated.

Set null to true in your img field like:
img = models.ImageField('personal_img',upload_to="personalcolor/", blank=True, null=True)
Then in your migrations folder within the app where the Personalcolor model is located, delete all of the files that look like 000*_initial.py
Then run makemigrations and migrate

Related

"Try it out" does not work in springdoc-openapi-ui?

I use springdoc-openapi-ui:1.6.9 to generate documentation, and I have this controller:
#Operation(summary = "Get a file meta by its ID")
#ApiResponses({
#ApiResponse(responseCode = "200", content = {
#Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = #Schema(implementation = FileMetaResponse.class))
}),
#ApiResponse(responseCode = "404", description = "Not found", content = {
#Content(mediaType = MediaType.TEXT_PLAIN_VALUE,
schema = #Schema(implementation = String.class))
})
})
#RequestMapping(value = "/files/meta", method = RequestMethod.GET)
public ResponseEntity<Object> getFileMate(#RequestParam final #NotEmpty String id) {
OssFile ossFIle = fileService.findFileById(UUID.fromString(id));
if (ossFIle == null) {
return new ResponseEntity<>("File not found", HttpStatus.NOT_FOUND);
}
FileMetaResponse body = new FileMetaResponse();
BeanUtils.copyProperties(ossFIle, body);
return new ResponseEntity<>(body, HttpStatus.OK);
}
But, I always got code 200 and no response body When I execute a request to this API with any id. By debugging code, I found that this request didn't arrive to backend. ui shows:
enter image description here
However, it works normally when I delete response mediatype definition, as follows:
/**
* Get a file meta by given a file ID.
*
* #param id file uuid
* #return a found OssFile meta if successful
*/
#Operation(summary = "Get a file meta by its ID")
#ApiResponses({
#ApiResponse(responseCode = "200", content = {
#Content(
schema = #Schema(implementation = FileMetaResponse.class))
}),
#ApiResponse(responseCode = "404", description = "Not found", content = {
#Content(
schema = #Schema(implementation = String.class))
})
})
#RequestMapping(value = "/files/meta", method = RequestMethod.GET)
public ResponseEntity<Object> getFileMate(#RequestParam final #NotEmpty String id) {
OssFile ossFIle = fileService.findFileById(UUID.fromString(id));
if (ossFIle == null) {
return new ResponseEntity<>("File not found", HttpStatus.NOT_FOUND);
}
FileMetaResponse body = new FileMetaResponse();
BeanUtils.copyProperties(ossFIle, body);
return new ResponseEntity<>(body, HttpStatus.OK);
}
By comparing the two requests, the Accept field of request header is different: the accept is application/json when media type is defined, otherwise the accept is */*.
If I want to define response media type and execute request on swagger-ui web, How should I do?

How to insert data in child table from react to django rest framework models

I'm new to React and Django rest framework. I want to insert profile data into the Django model using fetch API in react. I'm continuously getting response header as:
{"user":["Incorrect type. Expected pk value, received str."]}
I've checked by printing response on console, and it gives status code '200 OK'. But it didn't update the database as well.
My submit form function in react is:
const handleSubmit = (e) => {
e.preventDefault();
const profile = profileObj(selectedProfileImg, contact, city, country, address);
localStorage.setItem('profile', JSON.stringify(profile))
let form_data = new FormData()
// *************************
// this is the foreign key in the model and it gives the problem.
// *************************
form_data.append('user',JSON.parse(localStorage.getItem('data')).id) // (foriegn key value) User added by signing up
form_data.append('profile_img', profile.prof_img)
form_data.append('contact',profile.contact)
form_data.append('city',profile.city)
form_data.append('country',profile.country)
form_data.append('address',profile.address)
form_data.append('store_title','storename') // (foriegn key value) Data with this key exists in database
form_data.append('cus_status',profile.cus_status)
// *********************************
// Also I want to know what the boundary means in content
// type. As I see it on google so I used it but removing it
// gives another boundary error.
// *********************************
fetch('http://localhost:8000/customer_apis/addCustomer/', {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW'
},
body: form_data
})
.then(res => {
console.log(res)
console.log(res.status)
if (res.status !== 200)
document.getElementById('text-error').innerHTML = res.statusText
else {
navigate('/create_store')
}
})
}
My Django model is:
class CustomerData(models.Model):
CUS_STATUS=(
('A','Active'),
('B','Blocked'),
('X','Blacklist')
)
# I imported the user as (from django.contrib.auth.models import User)
user=models.ForeignKey(User, on_delete=models.CASCADE)
store_title=models.ForeignKey(StoreData, on_delete=models.CASCADE, null=True, default='')
city=models.CharField(max_length=50, default="")
country=models.CharField(max_length=50, default="")
address=models.CharField(max_length=200, default="")
phone=models.IntegerField(default=00)
profile_img=models.ImageField(upload_to=user_directory_path, blank=True,null=True)
cus_status=models.CharField(max_length=20,choices=CUS_STATUS, default='A')
def __str__(self):
return str(self.store_title)
And Django API view is:
#api_view(['POST','GET'])
def addCustomer(request):
serializer = CustomerSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response("Success")
else:
return Response(serializer.errors)
CustomerSerializer is:
class CustomerSerializer(serializers.ModelSerializer):
class Meta:
model = CustomerData
fields='__all__'
How could I add data to the child table having foreign keys from React Apis to Django rest Framework?
Any help will be really appreciated.
I think you need to use some other field for uploading user and store_title data.
class CustomerSerializer(serializers.ModelSerializer):
user_id = serializers.IntegerField(write_only = True)
store_title_id = serializers.IntegerField(write_only = True)
user = UserSerializer(read_only = True)
store_title = StoreTitleSerializer(read_only = True)
class Meta:
model = CustomerData
fields=("user", "store_title", "city", "country", "address", "phone", "profile_img", "cus_status", "user_id", "store_title_id", )
And in frontend, you can upload user_id and store_title_id as the integer value.
const handleSubmit = (e) => {
...
form_data.append('user_id', parseInt(JSON.parse(localStorage.getItem('data')).id, 10))
...
form_data.append('store_title_id', 1) # for example
...

"'Image' object is not callable" when posting API object

Update 2, 13th Jan: After doing some bug searching and trying to post the object directly in the root API using json, I've come to the realisation that the image is what's giving me the posting error.
I used the HTML form to post an object and it gave me this error:
TypeError at /rats/
'Image' object is not callable
For context, I uploaded an image. Here are my serialisers for creating the object (rat) and for images:
class ImageSerializer(FlexFieldsModelSerializer):
image = VersatileImageFieldSerializer(
sizes='rat_headshot'
)
class Meta:
model = Image
fields = ['name', 'image']
class RatSerializer(FlexFieldsModelSerializer):
user = serializers.CharField(source='user.username', required=False)
userid = serializers.CharField(source='user.id', required=False)
body_colour = BodyColourSerializer()
eye_colour = EyeColourSerializer()
image = ImageSerializer(required=False)
class Meta:
model = rat
exclude = ['bio']
def create(self, data):
request = self.context.get("request")
print("I was here", data, request)
return rat.objects.create(
name = data["name"],
body_colour = BodyColour(name=data["body_colour"]["name"]),
eye_colour = EyeColour(name=data["eye_colour"]["name"]),
# bio = data["bio"],
image = Image(name=data["image"]["name"])(required=False),
user = request.user,
)
I've updated the title. Original title was "Can't manage to post an object via axios to django - possibly due to AnonymousUser object?", now it's " "'Image' object is not callable" when posting API object "
Update 8th Jan: I fixed the AnonymousUser error. Django wanted an ID but was instead getting the user class, I fixed it by changing user = request.user into user = request.user.id
However, I'm still unable to post the object. I'm getting the same res.data error as below. So now I'm not sure what's causing the error.
I'm trying to add a button in React which posts an object to django via axios when a user clicks on it. However, it seems like something's wrong backend.
Here's the button:
<button
id="add-rat"
type="button"
className="btn homeButton"
onClick={
(e) => submit(e)
}
>
Add rat
</button>
And here's the axios, in the same page:
const submit = (e) => {
const name = "namee";
const eyeColour = "Red";
const bodyColour = "White";
const bio = "hfff";
const image = "lineart.PNG";
const data = {
name: name,
eye_colour: eyeColour,
body_colour: bodyColour,
bio: bio,
image: image,
};
e.preventDefault();
console.log(data);
const token = localStorage.getItem("token");
axios
.post("http://127.0.0.1:8000/api/addObject", data, {
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
})
.then((res) => {
console.log(res.data);
})
.catch((err) => console.log(err));
};
This is my console output:
{name: 'namee',
eye_colour: 'Red', body_colour: 'White', bio: 'hfff', image: 'lineart.PNG'}
myRats.js:86 {res: 'Error Accured'}
(myRats.js:86 btw, is console.log(res.data); )
Here's my view for the object:
class AddRat(APIView):
def post(self,request):
data = request.data
user = request.user
print(data)
try:
user = rat( name = data['name'] , body_colour = data['bodyColour'] , eye_colour = data['eyeColour'],user= user, bio = data['bio'] , image = data['image'])
user.save()
return Response({'res':"Rat Saved Successfully"})
except:
return Response({'res':"Error Accured"})
def get(self,request):
user = request.user
data = rat.objects.filter(user = user)
data = RatSerializer(data, many = True)
return Response({'data':data.data})
When I go to the url it's posting to, I get this error:
TypeError at /api/addObject
Field 'id' expected a number but got <django.contrib.auth.models.AnonymousUser object at 0x0000014641FD85B0>.
Could it possibly be due to that? What could be wrong?
The Anonymous User issue was solved by changing user = request.user into user = request.user.id
And my second issue, "'Image' object is not callable" was due to me putting (required=False) in another set of parenthesis, as if I was calling an Image as a function.
So I changed
image = Image(name=data["image"]["name"])(required=False)
into
image = Image(name=data["image"]["name"], required=False)

'ControllerBase.File(byte[], string)' is a method, which is not valid in the given context (CS0119) - in method

I am trying to create an app where user can upload a text file, and gets the altered text back.
I am using React as FE and ASP.NET Core for BE and Azure storage for the database storage.
This is how my HomeController looks like.
I created a separate "UploadToBlob" method, to post the data
public class HomeController : Controller
{
private readonly IConfiguration _configuration;
public HomeController(IConfiguration Configuration)
{
_configuration = Configuration;
}
public IActionResult Index()
{
return View();
}
[HttpPost("UploadFiles")]
//OPTION B: Uncomment to set a specified upload file limit
[RequestSizeLimit(40000000)]
public async Task<IActionResult> Post(List<IFormFile> files)
{
var uploadSuccess = false;
string uploadedUri = null;
foreach (var formFile in files)
{
if (formFile.Length <= 0)
{
continue;
}
// read directly from stream for blob upload
using (var stream = formFile.OpenReadStream())
{
// Open the file and upload its data
(uploadSuccess, uploadedUri) = await UploadToBlob(formFile.FileName, null, stream);
}
}
if (uploadSuccess)
{
//return the data to the view, which is react display text component.
return View("DisplayText");
}
else
{
//create an error component to show there was some error while uploading
return View("UploadError");
}
}
private async Task<(bool uploadSuccess, string uploadedUri)> UploadToBlob(string fileName, object p, Stream stream)
{
if (stream is null)
{
try
{
string connectionString = Environment.GetEnvironmentVariable("AZURE_STORAGE_CONNECTION_STRING");
// Create a BlobServiceClient object which will be used to create a container client
BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString);
//Create a unique name for the container
string containerName = "textdata" + Guid.NewGuid().ToString();
// Create the container and return a container client object
BlobContainerClient containerClient = await blobServiceClient.CreateBlobContainerAsync(containerName);
string localPath = "./data/";
string textFileName = "textdata" + Guid.NewGuid().ToString() + ".txt";
string localFilePath = Path.Combine(localPath, textFileName);
// Get a reference to a blob
BlobClient blobClient = containerClient.GetBlobClient(textFileName);
Console.WriteLine("Uploading to Blob storage as blob:\n\t {0}\n", blobClient.Uri);
FileStream uploadFileStream = File.OpenRead(localFilePath);
await blobClient.UploadAsync(uploadFileStream, true);
uploadFileStream.Close();
}
catch (StorageException)
{
return (false, null);
}
finally
{
// Clean up resources, e.g. blob container
//if (blobClient != null)
//{
// await blobClient.DeleteIfExistsAsync();
//}
}
}
else
{
return (false, null);
}
}
}
but the console throws errors, saying "'ControllerBase.File(byte[], string)' is a method, which is not valid in the given context (CS0119)"
And because of this error, another error follows "'HomeController.UploadToBlob(string, object, Stream)': not all code paths return a value (CS0161)"
my questions are
Is it a better idea to create a separate method like I did?
how can I resolve the issue regarding the "File" being valid inside of the UploadToBlob method?
If I want to add the file type validation, where should it happen? t.ex. only text file is alid
If I want to read the text string from the uploaded text file, where should I call the
string contents = blob.DownloadTextAsync().Result;
return contents;
How can I pass down the "contents" to my react component? something like this?
useEffect(() => {
fetch('Home')
.then(response => response.json())
.then(data => {
setForcasts(data)
})
}, [])
Thanks for helping this super newbie with ASP.NET Core!
1) It is ok to put uploading into separate method, it could also be put into a separate class for handling blob operations
2) File is the name of one of the controllers methods, if you want to reference the File class from System.IO namespace, you need to fully qualify the name
FileStream uploadFileStream = System.IO.File.OpenRead(localFilePath);
To the other compile error, you need to return something from the UploadToBlob method, now it does not return anything from the try block
3) File type validation can be put into the controller action method
4) it depends on what you plan to do with the text and how are you going to use it. Would it be a new action of the controller (a new API endpoint)?
5) you could create a new API endpoint for downloading files
UPDATE:
For word replacement you could use a similar method:
private Stream FindMostFrequentWordAndReplaceIt(Stream inputStream)
{
using (var sr = new StreamReader(inputStream, Encoding.UTF8)) // what is the encoding of the text?
{
var allText = sr.ReadToEnd(); // read all text into memory
// TODO: Find most frequent word in allText
// replace the word allText.Replace(oldValue, newValue, stringComparison)
var resultText = allText.Replace(...);
var result = new MemoryStream();
using (var sw = new StreamWriter(result))
{
sw.Write(resultText);
}
result.Position = 0;
return result;
}
}
it would be used in your Post method this way:
using (var stream = formFile.OpenReadStream())
{
var streamWithReplacement = FindMostFrequentWordAndReplaceIt(stream);
// Upload the replaced text:
(uploadSuccess, uploadedUri) = await UploadToBlob(formFile.FileName, null, streamWithReplacement);
}
You probably have this method inside MVC controller in which File method exists. Add in your code System.IO.File instead of File

Asp.net core file upload with Graphql-dotnet

I am trying to upload an image file with graphql-dotnet, but it is never successful.
I am taking file object in my GraphQLController:
var files = this.Request.Form.Files;
var executionOptions = new ExecutionOptions
{
Schema = _schema,
Query = queryToExecute,
Inputs = inputs,
UserContext = files,
OperationName = query.OperationName
};
And here my Mutation:
Field<UserGraphType>(
"uploadUserAvatar",
Description="Kullanıcı resmi yükleme.",
arguments: new QueryArguments(
new QueryArgument<NonNullGraphType<IntGraphType>> { Name = "Id", Description = "Identity Alanı" }
),
resolve: context => {
var file = context.UserContext.As<IFormCollection>();
var model = userService.UploadAvatar(context.GetArgument<int>("Id"),file);
return true;
}
);
I think it is accepting the only JSON. It is not accepting the request as a file type.
Also I am using React & apollo-client at the client-side. It has an error in the console:
Failed to load http://localhost:5000/graphql: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. The response had HTTP status code 500. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
I am trying to send the query like this:
const { selectedFile,id } = this.state
this.props.uploadAvatar({
variables: {id},
file:selectedFile
}).then(result => {
console.log(result);
});
What can I do to achieve this?
Failed to load http://localhost:5000/graphql: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:8080' is therefore not allowed
access.
This error means you need to enable CORS.
See these docs: https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.1
Essentially you need these two things:
services.AddCors();
app.UseCors(builder =>
builder.WithOrigins("http://example.com"));
I would also suggest to look at this Deserializer helper function in the GraphQL.Relay project. It helps your server handle a multipart/form-data request. You can then use the parsed query information and files and pass it to the DocumentExecutor.
https://github.com/graphql-dotnet/relay/blob/master/src/GraphQL.Relay/Http/Deserializer.cs
public static class Deserializer
{
public static async Task<RelayRequest> Deserialize(Stream body, string contentType)
{
RelayRequest queries;
switch (contentType)
{
case "multipart/form-data":
queries = DeserializeFormData(body);
break;
case "application/json":
var stream = new StreamReader(body);
queries = DeserializeJson(await stream.ReadToEndAsync());
break;
default:
throw new ArgumentOutOfRangeException($"Unknown media type: {contentType}. Cannot deserialize the Http request");
}
return queries;
}
private static RelayRequest DeserializeJson(string stringContent)
{
if (stringContent[0] == '[')
return new RelayRequest(
JsonConvert.DeserializeObject<RelayQuery[]>(stringContent),
isBatched: true
);
if (stringContent[0] == '{')
return new RelayRequest() {
JsonConvert.DeserializeObject<RelayQuery>(stringContent)
};
throw new Exception("Unrecognized request json. GraphQL queries requests should be a single object, or an array of objects");
}
private static RelayRequest DeserializeFormData(Stream body)
{
var form = new MultipartFormDataParser(body);
var req = new RelayRequest()
{
Files = form.Files.Select(f => new HttpFile {
ContentDisposition = f.ContentDisposition,
ContentType = f.ContentType,
Data = f.Data,
FileName = f.FileName,
Name = f.Name
})
};
req.Add(new RelayQuery {
Query = form.Parameters.Find(p => p.Name == "query").Data,
Variables = form.Parameters.Find(p => p.Name == "variables").Data.ToInputs(),
});
return req;
}
}

Resources